diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Sun Dec 21 00:13:14 2003 +++ b/MAINTAINERS Sun Dec 21 00:13:14 2003 @@ -929,8 +929,9 @@ S: Maintained SN-IA64 (Itanium) SUB-PLATFORM -P: John Hesterberg -M: jh@sgi.com +P: Jesse Barnes +M: jbarnes@sgi.com +L: linux-altix@sgi.com L: linux-ia64@linuxia64.org W: http://www.sgi.com/altix S: Maintained diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig --- a/arch/ia64/Kconfig Sun Dec 21 00:13:15 2003 +++ b/arch/ia64/Kconfig Sun Dec 21 00:13:15 2003 @@ -375,6 +375,11 @@ depends on IA32_SUPPORT default y +config HAVE_DEC_LOCK + bool + depends on (SMP || PREEMPT) + default y + config PERFMON bool "Performance monitor support" help @@ -394,16 +399,6 @@ To use this option, you have to ensure that the "/proc file system support" (CONFIG_PROC_FS) is enabled, too. -config IA64_SALINFO - tristate "/proc/sal support" - help - The /proc/sal directory exports the SAL (system abstraction layer) - feature bits, like whether the platform is subject to ITC drift. It - is intended to be used by user programs that care about such things. - - To use this option, you have to ensure that the "/proc file system - support" (CONFIG_PROC_FS) is enabled, too. - config EFI_VARS tristate "/proc/efi/vars support" help @@ -579,6 +574,7 @@ config IA64_GRANULE_64MB bool "64MB" + depends on !(IA64_GENERIC || IA64_HP_ZX1) endchoice @@ -620,6 +616,33 @@ send a BREAK and then within 5 seconds a command keypress. The keys are documented in . Don't say Y unless you really know what this hack does. + +config IA64_EARLY_PRINTK + bool "Early printk support" + depends on DEBUG_KERNEL && !IA64_GENERIC + help + Selecting this option uses the VGA screen or serial console for + printk() output before the consoles are initialised. It is useful + for debugging problems early in the boot process, but only if you + have a suitable VGA/serial console attached. If you're unsure, + select N. + +config IA64_EARLY_PRINTK_UART + bool "Early printk on MMIO serial port" + depends on IA64_EARLY_PRINTK + +config IA64_EARLY_PRINTK_UART_BASE + hex "UART MMIO base address" + depends on IA64_EARLY_PRINTK_UART + default "ff5e0000" + +config IA64_EARLY_PRINTK_VGA + bool "Early printk on VGA" + depends on IA64_EARLY_PRINTK + +config IA64_EARLY_PRINTK_SGI_SN + bool "Early printk on SGI SN serial console" + depends on IA64_EARLY_PRINTK && (IA64_GENERIC || IA64_SGI_SN2) config DEBUG_SLAB bool "Debug memory allocations" diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile --- a/arch/ia64/Makefile Sun Dec 21 00:13:14 2003 +++ b/arch/ia64/Makefile Sun Dec 21 00:13:14 2003 @@ -14,7 +14,7 @@ OBJCOPYFLAGS := --strip-all LDFLAGS_vmlinux := -static -LDFLAGS_MODULE += -T arch/ia64/module.lds +LDFLAGS_MODULE += -T $(srctree)/arch/ia64/module.lds AFLAGS_KERNEL := -mconstant-gp EXTRA := @@ -25,9 +25,9 @@ GCC_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.') GCC_MINOR_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f2 -d'.') -GAS_STATUS=$(shell arch/ia64/scripts/check-gas $(CC) $(OBJDUMP)) +GAS_STATUS=$(shell $(srctree)/arch/ia64/scripts/check-gas $(CC) $(OBJDUMP)) -CPPFLAGS += $(shell arch/ia64/scripts/toolchain-flags $(CC) $(OBJDUMP)) +CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags $(CC) $(OBJDUMP)) ifeq ($(GAS_STATUS),buggy) $(error Sorry, you need a newer version of the assember, one that is built from \ @@ -88,12 +88,15 @@ prepare: include/asm-ia64/offsets.h -include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s +arch/ia64/kernel/asm-offsets.s: include/asm include/linux/version.h + +include/asm-ia64/offsets.h: arch/ia64/kernel/asm-offsets.s $(call filechk,gen-asm-offsets) arch/ia64/kernel/asm-offsets.s: include/asm-ia64/.offsets.h.stamp include/asm-ia64/.offsets.h.stamp: + mkdir -p include/asm-ia64 [ -s include/asm-ia64/offsets.h ] \ || echo "#define IA64_TASK_SIZE 0" > include/asm-ia64/offsets.h touch $@ diff -Nru a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/configs/sn2_defconfig Sun Dec 21 00:13:15 2003 @@ -0,0 +1,693 @@ +# +# Automatically generated make config: don't edit +# + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_PAGG=y +CONFIG_PAGG_JOB=y +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=20 +# CONFIG_IKCONFIG is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Processor type and features +# +CONFIG_IA64=y +CONFIG_64BIT=y +CONFIG_MMU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_TIME_INTERPOLATION=y +# CONFIG_ITANIUM is not set +CONFIG_MCKINLEY=y +# CONFIG_IA64_GENERIC is not set +# CONFIG_IA64_DIG is not set +# CONFIG_IA64_HP_SIM is not set +# CONFIG_IA64_HP_ZX1 is not set +CONFIG_IA64_SGI_SN2=y +# CONFIG_IA64_PAGE_SIZE_4KB is not set +# CONFIG_IA64_PAGE_SIZE_8KB is not set +CONFIG_IA64_PAGE_SIZE_16KB=y +# CONFIG_IA64_PAGE_SIZE_64KB is not set +CONFIG_ACPI=y +CONFIG_ACPI_EFI=y +CONFIG_ACPI_INTERPRETER=y +CONFIG_ACPI_KERNEL_CONFIG=y +CONFIG_IA64_L1_CACHE_SHIFT=7 +# CONFIG_MCKINLEY_ASTEP_SPECIFIC is not set +CONFIG_NUMA=y +CONFIG_DISCONTIGMEM=y +CONFIG_VIRTUAL_MEM_MAP=y +CONFIG_IA64_MCA=y +CONFIG_IOSAPIC=y +# CONFIG_IA64_SGI_SN_SIM is not set +CONFIG_FORCE_MAX_ZONEORDER=18 +# CONFIG_IA64_PAL_IDLE is not set +CONFIG_SMP=y +# CONFIG_PREEMPT is not set +CONFIG_IA32_SUPPORT=y +CONFIG_COMPAT=y +CONFIG_PERFMON=y +CONFIG_IA64_PALINFO=y +CONFIG_IA64_SALINFO=y +# CONFIG_EFI_VARS is not set +CONFIG_NR_CPUS=512 +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI_BOOT=y +# CONFIG_ACPI_BUTTON is not set +# CONFIG_ACPI_FAN is not set +# CONFIG_ACPI_PROCESSOR is not set +CONFIG_ACPI_NUMA=y +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_BUS=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_PCI=y +CONFIG_ACPI_SYSTEM=y +# CONFIG_ACPI_RELAXED_AML is not set +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_HOTPLUG=y + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# PCMCIA/CardBus support +# +# CONFIG_PCMCIA is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR 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_REPORT_LUNS=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA 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_IPS is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +CONFIG_SCSI_QLOGIC_1280=y +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +CONFIG_ARPD=y +# CONFIG_INET_ECN is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT 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 + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +# CONFIG_NET_ETHERNET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +CONFIG_TIGON3=y + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI 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 +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_ROCKETPORT is not set +# CONFIG_SYNCLINK is not set +# CONFIG_SYNCLINKMP is not set +# CONFIG_N_HDLC is not set +# CONFIG_STALDRV is not set +CONFIG_SGI_L1_SERIAL=y +CONFIG_SGI_L1_SERIAL_CONSOLE=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Algorithms +# + +# +# I2C Hardware Bus support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_GEN_RTC is not set +CONFIG_EFI_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_XFS_FS=y +# CONFIG_XFS_RT is not set +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +CONFIG_EFI_PARTITION=y +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Library routines +# +CONFIG_CRC32=y + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_IA64_GRANULE_16MB is not set +CONFIG_IA64_GRANULE_64MB=y +CONFIG_DEBUG_KERNEL=y +# CONFIG_IA64_PRINT_HAZARDS is not set +# CONFIG_DISABLE_VHPT is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_IA64_EARLY_PRINTK=y +# CONFIG_IA64_EARLY_PRINTK_UART is not set +# CONFIG_IA64_EARLY_PRINTK_VGA is not set +CONFIG_IA64_EARLY_PRINTK_SGI_SN=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_IA64_DEBUG_CMPXCHG is not set +# CONFIG_IA64_DEBUG_IRQ is not set +# CONFIG_DEBUG_INFO is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set diff -Nru a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile --- a/arch/ia64/kernel/Makefile Sun Dec 21 00:13:15 2003 +++ b/arch/ia64/kernel/Makefile Sun Dec 21 00:13:15 2003 @@ -6,7 +6,7 @@ obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \ irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \ - semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o unwind.o + salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o unwind.o obj-$(CONFIG_EFI_VARS) += efivars.o obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o @@ -14,7 +14,6 @@ obj-$(CONFIG_IA64_HP_ZX1) += acpi-ext.o obj-$(CONFIG_IA64_MCA) += mca.o mca_asm.o obj-$(CONFIG_IA64_PALINFO) += palinfo.o -obj-$(CONFIG_IA64_SALINFO) += salinfo.o obj-$(CONFIG_IOSAPIC) += iosapic.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_SMP) += smp.o smpboot.o diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c --- a/arch/ia64/kernel/acpi.c Sun Dec 21 00:13:14 2003 +++ b/arch/ia64/kernel/acpi.c Sun Dec 21 00:13:14 2003 @@ -413,7 +413,7 @@ break; } if (p < pend) { - for (q = pend; q >= p; q--) + for (q = pend - 1; q >= p; q--) *(q + 1) = *q; } p->start_paddr = paddr; @@ -608,66 +608,6 @@ /* Make boot-up look pretty */ printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, total_cpus); return 0; -} - -/* - * PCI Interrupt Routing - */ - -#ifdef CONFIG_PCI -int __init -acpi_get_prt (struct pci_vector_struct **vectors, int *count) -{ - struct pci_vector_struct *vector; - struct list_head *node; - struct acpi_prt_entry *entry; - int i = 0; - - if (!vectors || !count) - return -EINVAL; - - *vectors = NULL; - *count = 0; - - if (acpi_prt.count < 0) { - printk(KERN_ERR PREFIX "No PCI interrupt routing entries\n"); - return -ENODEV; - } - - /* Allocate vectors */ - - *vectors = kmalloc(sizeof(struct pci_vector_struct) * acpi_prt.count, GFP_KERNEL); - if (!(*vectors)) - return -ENOMEM; - - /* Convert PRT entries to IOSAPIC PCI vectors */ - - vector = *vectors; - - list_for_each(node, &acpi_prt.entries) { - entry = (struct acpi_prt_entry *)node; - vector[i].segment = entry->id.segment; - vector[i].bus = entry->id.bus; - vector[i].pci_id = ((u32) entry->id.device << 16) | 0xffff; - vector[i].pin = entry->pin; - vector[i].irq = entry->link.index; - i++; - } - *count = acpi_prt.count; - return 0; -} -#endif /* CONFIG_PCI */ - -/* Assume IA64 always use I/O SAPIC */ - -int __init -acpi_get_interrupt_model (int *type) -{ - if (!type) - return -EINVAL; - - *type = ACPI_IRQ_MODEL_IOSAPIC; - return 0; } int diff -Nru a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c --- a/arch/ia64/kernel/asm-offsets.c Sun Dec 21 00:13:15 2003 +++ b/arch/ia64/kernel/asm-offsets.c Sun Dec 21 00:13:15 2003 @@ -12,6 +12,7 @@ #include #include #include +#include #include "../kernel/sigframe.h" @@ -203,5 +204,8 @@ #if CLONE_SETTLS != (1<<19) # error "CLONE_SETTLS_BIT incorrect, please fix" #endif + + BLANK(); + DEFINE(IA64_MCA_TLB_INFO_SIZE, sizeof (struct ia64_mca_tlb_info)); } diff -Nru a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c --- a/arch/ia64/kernel/efi.c Sun Dec 21 00:13:14 2003 +++ b/arch/ia64/kernel/efi.c Sun Dec 21 00:13:14 2003 @@ -30,6 +30,7 @@ #include #include #include +#include #define EFI_DEBUG 0 @@ -395,6 +396,9 @@ int pal_code_count = 0; u64 mask, psr; u64 vaddr; +#ifdef CONFIG_IA64_MCA + int cpu; +#endif efi_map_start = __va(ia64_boot_param->efi_memmap); efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; @@ -455,6 +459,14 @@ IA64_GRANULE_SHIFT); ia64_set_psr(psr); /* restore psr */ ia64_srlz_i(); + +#ifdef CONFIG_IA64_MCA + cpu = smp_processor_id(); + + /* insert this TR into our list for MCA recovery purposes */ + ia64_mca_tlb_list[cpu].pal_base = vaddr & mask; + ia64_mca_tlb_list[cpu].pal_paddr = pte_val(mk_pte_phys(md->phys_addr, PAGE_KERNEL)); +#endif } } diff -Nru a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S --- a/arch/ia64/kernel/gate.S Sun Dec 21 00:13:15 2003 +++ b/arch/ia64/kernel/gate.S Sun Dec 21 00:13:15 2003 @@ -195,10 +195,10 @@ ld8 r15=[base1] // get address of new RBS base (or NULL) cover // push args in interrupted frame onto backing store ;; - cmp.ne p8,p0=r15,r0 // do we need to switch the rbs? + cmp.ne p1,p0=r15,r0 // do we need to switch rbs? (note: pr is saved by kernel) mov.m r9=ar.bsp // fetch ar.bsp - .spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF -(p8) br.cond.spnt setup_rbs // yup -> (clobbers p8, r14-r16, and r18-r20) + .spillsp.p p1, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF +(p1) br.cond.spnt setup_rbs // yup -> (clobbers p8, r14-r16, and r18-r20) back_from_setup_rbs: alloc r8=ar.pfs,0,0,3,0 ld8 out0=[base0],16 // load arg0 (signum) @@ -237,8 +237,8 @@ ld8 r15=[base0],(CFM_OFF-BSP_OFF) // fetch sc_ar_bsp and advance to CFM_OFF mov r14=ar.bsp ;; - cmp.ne p8,p0=r14,r15 // do we need to restore the rbs? -(p8) br.cond.spnt restore_rbs // yup -> (clobbers r14-r18, f6 & f7) + cmp.ne p1,p0=r14,r15 // do we need to restore the rbs? +(p1) br.cond.spnt restore_rbs // yup -> (clobbers r14-r18, f6 & f7) ;; back_from_restore_rbs: adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp diff -Nru a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S --- a/arch/ia64/kernel/head.S Sun Dec 21 00:13:14 2003 +++ b/arch/ia64/kernel/head.S Sun Dec 21 00:13:14 2003 @@ -864,7 +864,7 @@ * the clobber lists for spin_lock() in include/asm-ia64/spinlock.h. */ -#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) +#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3) GLOBAL_ENTRY(ia64_spinlock_contention_pre3_4) .prologue diff -Nru a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c --- a/arch/ia64/kernel/ia64_ksyms.c Sun Dec 21 00:13:14 2003 +++ b/arch/ia64/kernel/ia64_ksyms.c Sun Dec 21 00:13:14 2003 @@ -189,7 +189,7 @@ EXPORT_SYMBOL(unw_access_pr); #ifdef CONFIG_SMP -# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) +# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3) /* * This is not a normal routine and we don't want a function descriptor for it, so we use * a fake declaration here. diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c --- a/arch/ia64/kernel/iosapic.c Sun Dec 21 00:13:14 2003 +++ b/arch/ia64/kernel/iosapic.c Sun Dec 21 00:13:14 2003 @@ -628,9 +628,6 @@ iosapic_lists[num_iosapic].num_rte = num_rte; num_iosapic++; - printk(KERN_INFO " IOSAPIC v%x.%x, address 0x%lx, GSIs 0x%x-0x%x\n", - (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1); - if ((gsi_base == 0) && pcat_compat) { /* * Map the legacy ISA devices into the IOSAPIC data. Some of these may diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c --- a/arch/ia64/kernel/irq.c Sun Dec 21 00:13:15 2003 +++ b/arch/ia64/kernel/irq.c Sun Dec 21 00:13:15 2003 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -997,21 +998,37 @@ unsigned int irq = (unsigned long) data; int full_count = count, err; cpumask_t new_value, tmp; - const char *buf = buffer; +# define R_PREFIX_LEN 16 + char rbuf[R_PREFIX_LEN]; + int rlen; + int prelen; irq_desc_t *desc = irq_descp(irq); - int redir; if (!desc->handler->set_affinity) return -EIO; - if (buf[0] == 'r' || buf[0] == 'R') { - ++buf; - while (*buf == ' ') ++buf; - redir = 1; - } else - redir = 0; + /* + * If string being written starts with a prefix of 'r' or 'R' + * and some limited number of spaces, set IA64_IRQ_REDIRECTED. + * If more than (R_PREFIX_LEN - 2) spaces are passed, they won't + * all be trimmed as part of prelen, the untrimmed spaces will + * cause the hex parsing to fail, and this write() syscall will + * fail with EINVAL. + */ + + if (!count) + return -EINVAL; + rlen = min(sizeof(rbuf)-1, count); + if (copy_from_user(rbuf, buffer, rlen)) + return -EFAULT; + rbuf[rlen] = 0; + prelen = 0; + if (tolower(*rbuf) == 'r') { + prelen = strspn(rbuf, "Rr "); + irq |= IA64_IRQ_REDIRECTED; + } - err = parse_hex_value(buf, count, &new_value); + err = parse_hex_value(buffer+prelen, count-prelen, &new_value); if (err) return err; @@ -1024,7 +1041,7 @@ if (cpus_empty(tmp)) return -EINVAL; - desc->handler->set_affinity(irq | (redir? IA64_IRQ_REDIRECTED : 0), new_value); + desc->handler->set_affinity(irq, new_value); return full_count; } diff -Nru a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S --- a/arch/ia64/kernel/ivt.S Sun Dec 21 00:13:14 2003 +++ b/arch/ia64/kernel/ivt.S Sun Dec 21 00:13:14 2003 @@ -360,33 +360,6 @@ rfi END(alt_dtlb_miss) - //----------------------------------------------------------------------------------- - // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address) -ENTRY(page_fault) - ssm psr.dt - ;; - srlz.i - ;; - SAVE_MIN_WITH_COVER - alloc r15=ar.pfs,0,0,3,0 - mov out0=cr.ifa - mov out1=cr.isr - adds r3=8,r2 // set up second base pointer - ;; - ssm psr.ic | PSR_DEFAULT_BITS - ;; - srlz.i // guarantee that interruption collectin is on - ;; -(p15) ssm psr.i // restore psr.i - movl r14=ia64_leave_kernel - ;; - SAVE_REST - mov rp=r14 - ;; - adds out2=16,r12 // out2 = pointer to pt_regs - br.call.sptk.many b6=ia64_do_page_fault // ignore return address -END(page_fault) - .org ia64_ivt+0x1400 ///////////////////////////////////////////////////////////////////////////////////////// // 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45) @@ -458,6 +431,33 @@ DBG_FAULT(6) FAULT(6) END(ikey_miss) + + //----------------------------------------------------------------------------------- + // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address) +ENTRY(page_fault) + ssm psr.dt + ;; + srlz.i + ;; + SAVE_MIN_WITH_COVER + alloc r15=ar.pfs,0,0,3,0 + mov out0=cr.ifa + mov out1=cr.isr + adds r3=8,r2 // set up second base pointer + ;; + ssm psr.ic | PSR_DEFAULT_BITS + ;; + srlz.i // guarantee that interruption collectin is on + ;; +(p15) ssm psr.i // restore psr.i + movl r14=ia64_leave_kernel + ;; + SAVE_REST + mov rp=r14 + ;; + adds out2=16,r12 // out2 = pointer to pt_regs + br.call.sptk.many b6=ia64_do_page_fault // ignore return address +END(page_fault) .org ia64_ivt+0x1c00 ///////////////////////////////////////////////////////////////////////////////////////// diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c --- a/arch/ia64/kernel/mca.c Sun Dec 21 00:13:14 2003 +++ b/arch/ia64/kernel/mca.c Sun Dec 21 00:13:14 2003 @@ -36,6 +36,10 @@ * SAL 3.0 spec. * 00/03/29 C. Fleckenstein Fixed PAL/SAL update issues, began MCA bug fixes, logging issues, * added min save state dump, added INIT handler. + * + * 2003-12-08 Keith Owens + * smp_call_function() must not be called from interrupt context (can + * deadlock on tasklist_lock). Use keventd to call smp_call_function(). */ #include #include @@ -51,6 +55,7 @@ #include #include #include +#include #include #include @@ -78,17 +83,19 @@ u64 ia64_mca_stackframe[32]; u64 ia64_mca_bspstore[1024]; u64 ia64_init_stack[KERNEL_STACK_SIZE/8] __attribute__((aligned(16))); -u64 ia64_mca_sal_data_area[1356]; -u64 ia64_tlb_functional; u64 ia64_os_mca_recovery_successful; +u64 ia64_mca_serialize; static void ia64_mca_wakeup_ipi_wait(void); static void ia64_mca_wakeup(int cpu); static void ia64_mca_wakeup_all(void); static void ia64_log_init(int); extern void ia64_monarch_init_handler (void); extern void ia64_slave_init_handler (void); +static u64 ia64_log_get(int sal_info_type, u8 **buffer); extern struct hw_interrupt_type irq_type_iosapic_level; +struct ia64_mca_tlb_info ia64_mca_tlb_list[NR_CPUS]; + static struct irqaction cmci_irqaction = { .handler = ia64_mca_cmc_int_handler, .flags = SA_INTERRUPT, @@ -149,12 +156,14 @@ */ static int cpe_poll_enabled = 1; +extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size); + /* * ia64_mca_log_sal_error_record * - * This function retrieves a specified error record type from SAL, sends it to - * the system log, and notifies SALs to clear the record from its non-volatile - * memory. + * This function retrieves a specified error record type from SAL, + * wakes up any processes waiting for error records, and sends it to + * the system log. * * Inputs : sal_info_type (Type of error record MCA/CMC/CPE/INIT) * Outputs : platform error status @@ -162,11 +171,13 @@ int ia64_mca_log_sal_error_record(int sal_info_type, int called_from_init) { - int platform_err = 0; + u8 *buffer; + u64 size; + int platform_err; - /* Get the MCA error record */ - if (!ia64_log_get(sal_info_type, (prfunc_t)printk)) - return platform_err; /* no record retrieved */ + size = ia64_log_get(sal_info_type, &buffer); + if (!size) + return 0; /* TODO: * 1. analyze error logs to determine recoverability @@ -174,10 +185,10 @@ * 3. set ia64_os_mca_recovery_successful flag, if applicable */ + salinfo_log_wakeup(sal_info_type, buffer, size); platform_err = ia64_log_print(sal_info_type, (prfunc_t)printk); - /* temporary: only clear SAL logs on hardware-corrected errors - or if we're logging an error after an MCA-initiated reboot */ - if ((sal_info_type > 1) || (called_from_init)) + /* Clear logs from corrected errors in case there's no user-level logger */ + if (sal_info_type == SAL_INFO_TYPE_CPE || sal_info_type == SAL_INFO_TYPE_CMC) ia64_sal_clear_state_info(sal_info_type); return platform_err; @@ -450,7 +461,10 @@ ia64_mca_register_cpev (int cpev) { /* Register the CPE interrupt vector with SAL */ - if (ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0)) { + struct ia64_sal_retval isrv; + + isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0); + if (isrv.status) { printk(KERN_ERR "ia64_mca_platform_init: failed to register Corrected " "Platform Error interrupt vector with SAL.\n"); return; @@ -602,6 +616,30 @@ } /* + * ia64_mca_cmc_vector_disable_keventd + * + * Called via keventd (smp_call_function() is not safe in interrupt context) to + * disable the cmc interrupt vector. + */ +static void +ia64_mca_cmc_vector_disable_keventd(void *unused) +{ + on_each_cpu(ia64_mca_cmc_vector_disable, NULL, 1, 0); +} + +/* + * ia64_mca_cmc_vector_enable_keventd + * + * Called via keventd (smp_call_function() is not safe in interrupt context) to + * enable the cmc interrupt vector. + */ +static void +ia64_mca_cmc_vector_enable_keventd(void *unused) +{ + on_each_cpu(ia64_mca_cmc_vector_enable, NULL, 1, 0); +} + +/* * ia64_mca_init * * Do all the system level mca specific initialization. @@ -629,6 +667,8 @@ ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch; int i; s64 rc; + struct ia64_sal_retval isrv; + u64 timeout = IA64_MCA_RENDEZ_TIMEOUT; /* platform specific */ IA64_MCA_DEBUG("ia64_mca_init: begin\n"); @@ -644,23 +684,33 @@ */ /* Register the rendezvous interrupt vector with SAL */ - if ((rc = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT, - SAL_MC_PARAM_MECHANISM_INT, - IA64_MCA_RENDEZ_VECTOR, - IA64_MCA_RENDEZ_TIMEOUT, - SAL_MC_PARAM_RZ_ALWAYS))) - { + while (1) { + isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT, + SAL_MC_PARAM_MECHANISM_INT, + IA64_MCA_RENDEZ_VECTOR, + timeout, + SAL_MC_PARAM_RZ_ALWAYS); + rc = isrv.status; + if (rc == 0) + break; + if (rc == -2) { + printk(KERN_INFO "ia64_mca_init: increasing MCA rendezvous timeout from " + "%ld to %ld\n", timeout, isrv.v0); + timeout = isrv.v0; + continue; + } printk(KERN_ERR "ia64_mca_init: Failed to register rendezvous interrupt " "with SAL. rc = %ld\n", rc); return; } /* Register the wakeup interrupt vector with SAL */ - if ((rc = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP, - SAL_MC_PARAM_MECHANISM_INT, - IA64_MCA_WAKEUP_VECTOR, - 0, 0))) - { + isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP, + SAL_MC_PARAM_MECHANISM_INT, + IA64_MCA_WAKEUP_VECTOR, + 0, 0); + rc = isrv.status; + if (rc) { printk(KERN_ERR "ia64_mca_init: Failed to register wakeup interrupt with SAL. " "rc = %ld\n", rc); return; @@ -924,6 +974,9 @@ void ia64_return_to_sal_check(void) { + pal_processor_state_info_t *psp = (pal_processor_state_info_t *) + &ia64_sal_to_os_handoff_state.proc_state_param; + /* Copy over some relevant stuff from the sal_to_os_mca_handoff * so that it can be used at the time of os_mca_to_sal_handoff */ @@ -933,14 +986,22 @@ ia64_os_to_sal_handoff_state.imots_sal_check_ra = ia64_sal_to_os_handoff_state.imsto_sal_check_ra; - /* Cold Boot for uncorrectable MCA */ - ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT; + /* + * Did we correct the error? At the moment the only error that + * we fix is a TLB error, if any other kind of error occurred + * we must reboot. + */ + if (psp->cc == 1 && psp->bc == 1 && psp->rc == 1 && psp->uc == 1) + ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT; + else + ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_CORRECTED; /* Default = tell SAL to return to same context */ ia64_os_to_sal_handoff_state.imots_context = IA64_MCA_SAME_CONTEXT; ia64_os_to_sal_handoff_state.imots_new_min_state = (u64 *)ia64_sal_to_os_handoff_state.pal_min_state; + } /* @@ -983,6 +1044,9 @@ ia64_return_to_sal_check(); } +static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd, NULL); +static DECLARE_WORK(cmc_enable_work, ia64_mca_cmc_vector_enable_keventd, NULL); + /* * ia64_mca_cmc_int_handler * @@ -1029,14 +1093,7 @@ cmc_polling_enabled = 1; spin_unlock(&cmc_history_lock); - - /* - * We rely on the local_irq_enable() above so - * that this can't deadlock. - */ - ia64_mca_cmc_vector_disable(NULL); - - smp_call_function(ia64_mca_cmc_vector_disable, NULL, 1, 0); + schedule_work(&cmc_disable_work); /* * Corrected errors will still be corrected, but @@ -1131,19 +1188,7 @@ if (start_count == IA64_LOG_COUNT(SAL_INFO_TYPE_CMC)) { printk(KERN_WARNING "%s: Returning to interrupt driven CMC handler\n", __FUNCTION__); - - /* - * The cmc interrupt handler enabled irqs, so - * this can't deadlock. - */ - smp_call_function(ia64_mca_cmc_vector_enable, NULL, 1, 0); - - /* - * Turn off interrupts before re-enabling the - * cmc vector locally. Make sure we get out. - */ - local_irq_disable(); - ia64_mca_cmc_vector_enable(NULL); + schedule_work(&cmc_enable_work); cmc_polling_enabled = 0; } else { @@ -1318,8 +1363,8 @@ void ia64_log_prt_guid (efi_guid_t *p_guid, prfunc_t prfunc) { - char out[40]; - printk(KERN_DEBUG "GUID = %s\n", efi_guid_unparse(p_guid, out)); + //char out[40]; + //printk(KERN_DEBUG "GUID = %s\n", efi_guid_unparse(p_guid, out)); } static void @@ -1399,12 +1444,12 @@ * Get the current MCA log from SAL and copy it into the OS log buffer. * * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE}) - * prfunc (fn ptr of log output function) * Outputs : size (total record length) + * *buffer (ptr to error record) * */ -u64 -ia64_log_get(int sal_info_type, prfunc_t prfunc) +static u64 +ia64_log_get(int sal_info_type, u8 **buffer) { sal_log_record_header_t *log_buffer; u64 total_len = 0; @@ -1422,6 +1467,7 @@ IA64_LOG_UNLOCK(sal_info_type); IA64_MCA_DEBUG("ia64_log_get: SAL error record type %d retrieved. " "Record length = %ld\n", sal_info_type, total_len); + *buffer = (u8 *) log_buffer; return total_len; } else { IA64_LOG_UNLOCK(sal_info_type); @@ -1466,7 +1512,7 @@ void ia64_log_rec_header_print (sal_log_record_header_t *lh, prfunc_t prfunc) { - prfunc("+Err Record ID: %d SAL Rev: %2x.%02x\n", lh->id, + prfunc("+Err Record ID: %ld SAL Rev: %2x.%02x\n", lh->id, lh->revision.major, lh->revision.minor); prfunc("+Time: %02x/%02x/%02x%02x %02x:%02x:%02x Severity %d\n", lh->timestamp.slh_month, lh->timestamp.slh_day, @@ -1589,13 +1635,13 @@ if (info->dl) prfunc(" Line: Data,"); prfunc(" Operation: %s,", pal_cache_op[info->op]); - if (info->wv) + if (info->wiv) prfunc(" Way: %d,", info->way); if (cache_check_info->valid.target_identifier) /* Hope target address is saved in target_identifier */ if (info->tv) prfunc(" Target Addr: 0x%lx,", target_addr); - if (info->mc) + if (info->mcc) prfunc(" MC: Corrected"); prfunc("\n"); } @@ -1631,13 +1677,13 @@ prfunc(" Failure: Data Translation Cache"); if (info->itr) { prfunc(" Failure: Instruction Translation Register"); - prfunc(" ,Slot: %d", info->tr_slot); + prfunc(" ,Slot: %ld", info->tr_slot); } if (info->dtr) { prfunc(" Failure: Data Translation Register"); - prfunc(" ,Slot: %d", info->tr_slot); + prfunc(" ,Slot: %ld", info->tr_slot); } - if (info->mc) + if (info->mcc) prfunc(" ,MC: Corrected"); prfunc("\n"); } @@ -1683,7 +1729,7 @@ prfunc(" ,Error: Internal"); if (info->eb) prfunc(" ,Error: External"); - if (info->mc) + if (info->mcc) prfunc(" ,MC: Corrected"); if (info->tv) prfunc(" ,Target Address: 0x%lx", targ_addr); @@ -1970,9 +2016,9 @@ ia64_log_prt_guid(&psei->guid, prfunc); } if (psei->valid.oem_data) { - platform_plat_specific_err_print((int)psei->header.len, - (int)sizeof(sal_log_plat_specific_err_info_t) - 1, - &(psei->oem_data[0]), prfunc); + platform_plat_specific_err_print((int) psei->header.len, + (char *) psei->oem_data - (char *) psei, + &psei->oem_data[0], prfunc); } prfunc("\n"); } @@ -2352,13 +2398,12 @@ switch(sal_info_type) { case SAL_INFO_TYPE_MCA: - prfunc("+BEGIN HARDWARE ERROR STATE AT MCA\n"); - platform_err = ia64_log_platform_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), - prfunc); - prfunc("+END HARDWARE ERROR STATE AT MCA\n"); + prfunc("+CPU %d: SAL log contains MCA error record\n", smp_processor_id()); + ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc); break; case SAL_INFO_TYPE_INIT: - prfunc("+MCA INIT ERROR LOG (UNIMPLEMENTED)\n"); + prfunc("+CPU %d: SAL log contains INIT error record\n", smp_processor_id()); + ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc); break; case SAL_INFO_TYPE_CMC: prfunc("+BEGIN HARDWARE ERROR STATE AT CMC\n"); diff -Nru a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S --- a/arch/ia64/kernel/mca_asm.S Sun Dec 21 00:13:15 2003 +++ b/arch/ia64/kernel/mca_asm.S Sun Dec 21 00:13:15 2003 @@ -14,6 +14,7 @@ // 3. Move stack ptr 16 bytes to conform to C calling convention // #include +#include #include #include @@ -22,20 +23,15 @@ #include /* - * When we get an machine check, the kernel stack pointer is no longer + * When we get a machine check, the kernel stack pointer is no longer * valid, so we need to set a new stack pointer. */ #define MINSTATE_PHYS /* Make sure stack access is physical for MINSTATE */ /* - * Needed for ia64_sal call - */ -#define SAL_GET_STATE_INFO 0x01000001 - -/* * Needed for return context to SAL */ -#define IA64_MCA_SAME_CONTEXT 0x0 +#define IA64_MCA_SAME_CONTEXT 0 #define IA64_MCA_COLD_BOOT -2 #include "minstate.h" @@ -71,19 +67,36 @@ * returns ptr to SAL rtn save loc in _tmp */ #define OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(_tmp) \ - LOAD_PHYSICAL(p6, _tmp, ia64_sal_to_os_handoff_state);; \ - LOAD_PHYSICAL(p7, _tmp, ia64_os_to_sal_handoff_state);; \ -(p6) movl r8=IA64_MCA_COLD_BOOT; \ -(p6) movl r10=IA64_MCA_SAME_CONTEXT; \ -(p6) add _tmp=0x18,_tmp;; \ -(p6) ld8 r9=[_tmp],0x10; \ -(p6) mov r22=r0;; \ -(p7) ld8 r8=[_tmp],0x08;; \ -(p7) ld8 r9=[_tmp],0x08;; \ -(p7) ld8 r10=[_tmp],0x08;; \ -(p7) ld8 r22=[_tmp],0x08;; + movl _tmp=ia64_os_to_sal_handoff_state;; \ + DATA_VA_TO_PA(_tmp);; \ + ld8 r8=[_tmp],0x08;; \ + ld8 r9=[_tmp],0x08;; \ + ld8 r10=[_tmp],0x08;; \ + ld8 r22=[_tmp],0x08;; // now _tmp is pointing to SAL rtn save location +/* + * COLD_BOOT_HANDOFF_STATE() sets ia64_mca_os_to_sal_state + * imots_os_status=IA64_MCA_COLD_BOOT + * imots_sal_gp=SAL GP + * imots_context=IA64_MCA_SAME_CONTEXT + * imots_new_min_state=Min state save area pointer + * imots_sal_check_ra=Return address to location within SAL_CHECK + * + */ +#define COLD_BOOT_HANDOFF_STATE(sal_to_os_handoff,os_to_sal_handoff,tmp)\ + movl tmp=IA64_MCA_COLD_BOOT; \ + movl sal_to_os_handoff=__pa(ia64_sal_to_os_handoff_state); \ + movl os_to_sal_handoff=__pa(ia64_os_to_sal_handoff_state);; \ + st8 [os_to_sal_handoff]=tmp,8;; \ + ld8 tmp=[sal_to_os_handoff],48;; \ + st8 [os_to_sal_handoff]=tmp,8;; \ + movl tmp=IA64_MCA_SAME_CONTEXT;; \ + st8 [os_to_sal_handoff]=tmp,8;; \ + ld8 tmp=[sal_to_os_handoff],-8;; \ + st8 [os_to_sal_handoff]=tmp,8;; \ + ld8 tmp=[sal_to_os_handoff];; \ + st8 [os_to_sal_handoff]=tmp;; .global ia64_os_mca_dispatch .global ia64_os_mca_dispatch_end @@ -94,20 +107,21 @@ .global ia64_mca_stackframe .global ia64_mca_bspstore .global ia64_init_stack - .global ia64_mca_sal_data_area - .global ia64_tlb_functional .text .align 16 ia64_os_mca_dispatch: -#if defined(MCA_TEST) - // Pretend that we are in interrupt context - mov r2=psr - dep r2=0, r2, PSR_IC, 2; - mov psr.l = r2 -#endif /* #if defined(MCA_TEST) */ + // Serialize all MCA processing +// movl r2=ia64_mca_serialize + mov r3=1;; +// DATA_VA_TO_PA(r2);; + LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);; +ia64_os_mca_spin: + xchg8 r4=[r2],r3;; + cmp.ne p6,p0=r4,r0 +(p6) br ia64_os_mca_spin // Save the SAL to OS MCA handoff state as defined // by SAL SPEC 3.0 @@ -124,6 +138,191 @@ ia64_os_mca_done_dump: +// movl r16=__pa(ia64_sal_to_os_handoff_state)+56 + LOAD_PHYSICAL(p0,r16,ia64_sal_to_os_handoff_state+56) + ;; + ld8 r18=[r16] // Get processor state parameter on existing PALE_CHECK. + ;; + tbit.nz p6,p7=r18,60 +(p7) br.spnt done_tlb_purge_and_reload + + // The following code purges TC and TR entries. Then reload all TC entries. + // Purge percpu data TC entries. +begin_tlb_purge_and_reload: + mov r16=cr.lid +// movl r17=__pa(ia64_mca_tlb_list) // Physical address of ia64_mca_tlb_list + LOAD_PHYSICAL(p0,r17,ia64_mca_tlb_list) // Physical address of ia64_mca_tlb_list + mov r19=0 + mov r20=NR_CPUS + ;; +1: cmp.eq p6,p7=r19,r20 +(p6) br.spnt.few err + ld8 r18=[r17],IA64_MCA_TLB_INFO_SIZE + ;; + add r19=1,r19 + cmp.eq p6,p7=r18,r16 +(p7) br.sptk.few 1b + ;; + adds r17=-IA64_MCA_TLB_INFO_SIZE,r17 + ;; + mov r23=r17 // save current ia64_mca_percpu_info addr pointer. + adds r17=16,r17 + ;; + .global aegl +aegl: + ld8 r18=[r17],8 // r18=ptce_base + ;; + ld4 r19=[r17],4 // r19=ptce_count[0] + ;; + ld4 r20=[r17],4 // r20=ptce_count[1] + ;; + ld4 r21=[r17],4 // r21=ptce_stride[0] + mov r24=0 + ;; + ld4 r22=[r17],4 // r22=ptce_stride[1] + adds r20=-1,r20 + ;; +2: + cmp.ltu p6,p7=r24,r19 +(p7) br.cond.dpnt.few 4f + mov ar.lc=r20 +3: + ptc.e r18 + ;; + add r18=r22,r18 + br.cloop.sptk.few 3b + ;; + add r18=r21,r18 + add r24=1,r24 + ;; + br.sptk.few 2b +4: + srlz.i // srlz.i implies srlz.d + ;; + + // Now purge addresses formerly mapped by TR registers + // 1. Purge ITR&DTR for kernel. + movl r16=KERNEL_START + mov r18=KERNEL_TR_PAGE_SHIFT<<2 + ;; + ptr.i r16, r18 + ptr.d r16, r18 + ;; + srlz.i + ;; + srlz.d + ;; + // 2. Purge DTR for PERCPU data. + movl r16=PERCPU_ADDR + mov r18=PERCPU_PAGE_SHIFT<<2 + ;; + ptr.d r16,r18 + ;; + srlz.d + ;; + // 3. Purge ITR for PAL code. + adds r17=48,r23 + ;; + ld8 r16=[r17] + mov r18=IA64_GRANULE_SHIFT<<2 + ;; + ptr.i r16,r18 + ;; + srlz.i + ;; + // 4. Purge DTR for stack. + mov r16=IA64_KR(CURRENT_STACK) + ;; + shl r16=r16,IA64_GRANULE_SHIFT + movl r19=PAGE_OFFSET + ;; + add r16=r19,r16 + mov r18=IA64_GRANULE_SHIFT<<2 + ;; + ptr.d r16,r18 + ;; + srlz.i + ;; + // Finally reload the TR registers. + // 1. Reload DTR/ITR registers for kernel. + mov r18=KERNEL_TR_PAGE_SHIFT<<2 + movl r17=KERNEL_START + ;; + mov cr.itir=r18 + mov cr.ifa=r17 + mov r16=IA64_TR_KERNEL + mov r19=ip + movl r18=PAGE_KERNEL + ;; + dep r17=0,r19,0, KERNEL_TR_PAGE_SHIFT + ;; + or r18=r17,r18 + ;; + itr.i itr[r16]=r18 + ;; + itr.d dtr[r16]=r18 + ;; + srlz.i + srlz.d + ;; + // 2. Reload DTR register for PERCPU data. + adds r17=8,r23 + movl r16=PERCPU_ADDR // vaddr + movl r18=PERCPU_PAGE_SHIFT<<2 + ;; + mov cr.itir=r18 + mov cr.ifa=r16 + ;; + ld8 r18=[r17] // pte + mov r16=IA64_TR_PERCPU_DATA; + ;; + itr.d dtr[r16]=r18 + ;; + srlz.d + ;; + // 3. Reload ITR for PAL code. + adds r17=40,r23 + ;; + ld8 r18=[r17],8 // pte + ;; + ld8 r16=[r17] // vaddr + mov r19=IA64_GRANULE_SHIFT<<2 + ;; + mov cr.itir=r19 + mov cr.ifa=r16 + mov r20=IA64_TR_PALCODE + ;; + itr.i itr[r20]=r18 + ;; + srlz.i + ;; + // 4. Reload DTR for stack. + mov r16=IA64_KR(CURRENT_STACK) + ;; + shl r16=r16,IA64_GRANULE_SHIFT + movl r19=PAGE_OFFSET + ;; + add r18=r19,r16 + movl r20=PAGE_KERNEL + ;; + add r16=r20,r16 + mov r19=IA64_GRANULE_SHIFT<<2 + ;; + mov cr.itir=r19 + mov cr.ifa=r18 + mov r20=IA64_TR_CURRENT_STACK + ;; + itr.d dtr[r20]=r16 + ;; + srlz.d + ;; + br.sptk.many done_tlb_purge_and_reload +err: + COLD_BOOT_HANDOFF_STATE(r20,r21,r22) + br.sptk.many ia64_os_mca_done_restore + +done_tlb_purge_and_reload: + // Setup new stack frame for OS_MCA handling movl r2=ia64_mca_bspstore;; // local bspstore area location in r2 DATA_VA_TO_PA(r2);; @@ -137,17 +336,11 @@ // (C calling convention) DATA_VA_TO_PA(r12);; - // Check to see if the MCA resulted from a TLB error -begin_tlb_error_check: - br ia64_os_mca_tlb_error_check;; - -done_tlb_error_check: - - // If TLB is functional, enter virtual mode from physical mode + // Enter virtual mode from physical mode VIRTUAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_begin, r4) ia64_os_mca_virtual_begin: - // call our handler + // Call virtual mode handler movl r2=ia64_mca_ucmc_handler;; mov b6=r2;; br.call.sptk.many b0=b6;; @@ -156,13 +349,6 @@ PHYSICAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_end, r4) ia64_os_mca_virtual_end: -#if defined(MCA_TEST) - // Pretend that we are in interrupt context - mov r2=psr;; - dep r2=0, r2, PSR_IC, 2;; - mov psr.l = r2;; -#endif /* #if defined(MCA_TEST) */ - // restore the original stack frame here movl r2=ia64_mca_stackframe // restore stack frame from memory at r2 ;; @@ -178,14 +364,16 @@ br ia64_os_mca_proc_state_restore;; ia64_os_mca_done_restore: - movl r3=ia64_tlb_functional;; - DATA_VA_TO_PA(r3);; - ld8 r3=[r3];; - cmp.eq p6,p7=r0,r3;; OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(r2);; // branch back to SALE_CHECK ld8 r3=[r2];; mov b0=r3;; // SAL_CHECK return address + + // release lock + movl r3=ia64_mca_serialize;; + DATA_VA_TO_PA(r3);; + st8.rel [r3]=r0 + br b0 ;; ia64_os_mca_dispatch_end: @@ -205,8 +393,9 @@ ia64_os_mca_proc_state_dump: // Save bank 1 GRs 16-31 which will be used by c-language code when we switch // to virtual addressing mode. - movl r2=ia64_mca_proc_state_dump;; // Os state dump area - DATA_VA_TO_PA(r2) // convert to to physical address +// movl r2=ia64_mca_proc_state_dump;; // Os state dump area +// DATA_VA_TO_PA(r2) // convert to to physical address + LOAD_PHYSICAL(p0,r2,ia64_mca_proc_state_dump)// convert OS state dump area to physical address // save ar.NaT mov r5=ar.unat // ar.unat @@ -655,79 +844,6 @@ ;; end_os_mca_restore: br ia64_os_mca_done_restore;; - -//EndStub////////////////////////////////////////////////////////////////////// - -//++ -// Name: -// ia64_os_mca_tlb_error_check() -// -// Stub Description: -// -// This stub checks to see if the MCA resulted from a TLB error -// -//-- - -ia64_os_mca_tlb_error_check: - - // Retrieve sal data structure for uncorrected MCA - - // Make the ia64_sal_get_state_info() call - movl r4=ia64_mca_sal_data_area;; - movl r7=ia64_sal;; - mov r6=r1 // save gp - DATA_VA_TO_PA(r4) // convert to physical address - DATA_VA_TO_PA(r7);; // convert to physical address - ld8 r7=[r7] // get addr of pdesc from ia64_sal - movl r3=SAL_GET_STATE_INFO;; - DATA_VA_TO_PA(r7);; // convert to physical address - ld8 r8=[r7],8;; // get pdesc function pointer - dep r8=0,r8,61,3;; // convert SAL VA to PA - ld8 r1=[r7];; // set new (ia64_sal) gp - dep r1=0,r1,61,3;; // convert SAL VA to PA - mov b6=r8 - - alloc r5=ar.pfs,8,0,8,0;; // allocate stack frame for SAL call - mov out0=r3 // which SAL proc to call - mov out1=r0 // error type == MCA - mov out2=r0 // null arg - mov out3=r4 // data copy area - mov out4=r0 // null arg - mov out5=r0 // null arg - mov out6=r0 // null arg - mov out7=r0;; // null arg - - br.call.sptk.few b0=b6;; - - mov r1=r6 // restore gp - mov ar.pfs=r5;; // restore ar.pfs - - movl r6=ia64_tlb_functional;; - DATA_VA_TO_PA(r6) // needed later - - cmp.eq p6,p7=r0,r8;; // check SAL call return address -(p7) st8 [r6]=r0 // clear tlb_functional flag -(p7) br tlb_failure // error; return to SAL - - // examine processor error log for type of error - add r4=40+24,r4;; // parse past record header (length=40) - // and section header (length=24) - ld4 r4=[r4] // get valid field of processor log - mov r5=0xf00;; - and r5=r4,r5;; // read bits 8-11 of valid field - // to determine if we have a TLB error - movl r3=0x1 - cmp.eq p6,p7=r0,r5;; - // if no TLB failure, set tlb_functional flag -(p6) st8 [r6]=r3 - // else clear flag -(p7) st8 [r6]=r0 - - // if no TLB failure, continue with normal virtual mode logging -(p6) br done_tlb_error_check - // else no point in entering virtual mode for logging -tlb_failure: - br ia64_os_mca_virtual_end //EndStub////////////////////////////////////////////////////////////////////// diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c --- a/arch/ia64/kernel/perfmon.c Sun Dec 21 00:13:15 2003 +++ b/arch/ia64/kernel/perfmon.c Sun Dec 21 00:13:15 2003 @@ -5475,7 +5475,7 @@ int this_cpu; int ret; - this_cpu = smp_processor_id(); + this_cpu = get_cpu(); min = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min; max = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max; diff -Nru a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c --- a/arch/ia64/kernel/salinfo.c Sun Dec 21 00:13:15 2003 +++ b/arch/ia64/kernel/salinfo.c Sun Dec 21 00:13:15 2003 @@ -3,18 +3,31 @@ * * Creates entries in /proc/sal for various system features. * - * Copyright (c) 2001 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 2003 Hewlett-Packard Co + * Bjorn Helgaas * - * 09/11/2003 jbarnes@sgi.com updated for 2.6 * 10/30/2001 jbarnes@sgi.com copied much of Stephane's palinfo * code to create this file + * Oct 23 2003 kaos@sgi.com + * Replace IPI with set_cpus_allowed() to read a record from the required cpu. + * Redesign salinfo log processing to separate interrupt and user space + * contexts. + * Cache the record across multi-block reads from user space. + * Support > 64 cpus. + * Delete module_exit and MOD_INC/DEC_COUNT, salinfo cannot be a module. */ #include #include #include +#include +#include +#include +#include #include +#include MODULE_AUTHOR("Jesse Barnes "); MODULE_DESCRIPTION("/proc interface to IA-64 SAL features"); @@ -41,42 +54,511 @@ #define NR_SALINFO_ENTRIES ARRAY_SIZE(salinfo_entries) -/* - * One for each feature and one more for the directory entry... +static char *salinfo_log_name[] = { + "mca", + "init", + "cmc", + "cpe", +}; + +static struct proc_dir_entry *salinfo_proc_entries[ + ARRAY_SIZE(salinfo_entries) + /* /proc/sal/bus_lock */ + ARRAY_SIZE(salinfo_log_name) + /* /proc/sal/{mca,...} */ + (2 * ARRAY_SIZE(salinfo_log_name)) + /* /proc/sal/mca/{event,data} */ + 1]; /* /proc/sal */ + +/* Some records we get ourselves, some are accessed as saved data in buffers + * that are owned by mca.c. + */ +struct salinfo_data_saved { + u8* buffer; + u64 size; + u64 id; + int cpu; +}; + +/* State transitions. Actions are :- + * Write "read " to the data file. + * Write "clear " to the data file. + * Write "oemdata to the data file. + * Read from the data file. + * Close the data file. + * + * Start state is NO_DATA. + * + * NO_DATA + * write "read " -> NO_DATA or LOG_RECORD. + * write "clear " -> NO_DATA or LOG_RECORD. + * write "oemdata -> return -EINVAL. + * read data -> return EOF. + * close -> unchanged. Free record areas. + * + * LOG_RECORD + * write "read " -> NO_DATA or LOG_RECORD. + * write "clear " -> NO_DATA or LOG_RECORD. + * write "oemdata -> format the oem data, goto OEMDATA. + * read data -> return the INIT/MCA/CMC/CPE record. + * close -> unchanged. Keep record areas. + * + * OEMDATA + * write "read " -> NO_DATA or LOG_RECORD. + * write "clear " -> NO_DATA or LOG_RECORD. + * write "oemdata -> format the oem data, goto OEMDATA. + * read data -> return the formatted oemdata. + * close -> unchanged. Keep record areas. + * + * Closing the data file does not change the state. This allows shell scripts + * to manipulate salinfo data, each shell redirection opens the file, does one + * action then closes it again. The record areas are only freed at close when + * the state is NO_DATA. + */ +enum salinfo_state { + STATE_NO_DATA, + STATE_LOG_RECORD, + STATE_OEMDATA, +}; + +struct salinfo_data { + volatile cpumask_t cpu_event; /* which cpus have outstanding events */ + struct semaphore sem; /* count of cpus with outstanding events (bits set in cpu_event) */ + u8 *log_buffer; + u64 log_size; + u8 *oemdata; /* decoded oem data */ + u64 oemdata_size; + int open; /* single-open to prevent races */ + u8 type; + u8 saved_num; /* using a saved record? */ + enum salinfo_state state :8; /* processing state */ + u8 padding; + int cpu_check; /* next CPU to check */ + struct salinfo_data_saved data_saved[5];/* save last 5 records from mca.c, must be < 255 */ +}; + +static struct salinfo_data salinfo_data[ARRAY_SIZE(salinfo_log_name)]; + +static spinlock_t data_lock, data_saved_lock; + +/** salinfo_platform_oemdata - optional callback to decode oemdata from an error + * record. + * @sect_header: pointer to the start of the section to decode. + * @oemdata: returns vmalloc area containing the decded output. + * @oemdata_size: returns length of decoded output (strlen). + * + * Description: If user space asks for oem data to be decoded by the kernel + * and/or prom and the platform has set salinfo_platform_oemdata to the address + * of a platform specific routine then call that routine. salinfo_platform_oemdata + * vmalloc's and formats its output area, returning the address of the text + * and its strlen. Returns 0 for success, -ve for error. The callback is + * invoked on the cpu that generated the error record. */ -static struct proc_dir_entry *salinfo_proc_entries[NR_SALINFO_ENTRIES + 1]; +int (*salinfo_platform_oemdata)(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size); + +struct salinfo_platform_oemdata_parms { + const u8 *efi_guid; + u8 **oemdata; + u64 *oemdata_size; + int ret; +}; + +static void +salinfo_platform_oemdata_cpu(void *context) +{ + struct salinfo_platform_oemdata_parms *parms = context; + parms->ret = salinfo_platform_oemdata(parms->efi_guid, parms->oemdata, parms->oemdata_size); +} + +static void +shift1_data_saved (struct salinfo_data *data, int shift) +{ + memcpy(data->data_saved+shift, data->data_saved+shift+1, + (ARRAY_SIZE(data->data_saved) - (shift+1)) * sizeof(data->data_saved[0])); + memset(data->data_saved + ARRAY_SIZE(data->data_saved) - 1, 0, + sizeof(data->data_saved[0])); +} + +/* This routine is invoked in interrupt context. Note: mca.c enables + * interrupts before calling this code for CMC/CPE. MCA and INIT events are + * not irq safe, do not call any routines that use spinlocks, they may deadlock. + * + * The buffer passed from mca.c points to the output from ia64_log_get. This is + * a persistent buffer but its contents can change between the interrupt and + * when user space processes the record. Save the record id to identify + * changes. + */ +void +salinfo_log_wakeup(int type, u8 *buffer, u64 size) +{ + struct salinfo_data *data = salinfo_data + type; + struct salinfo_data_saved *data_saved; + unsigned long flags = 0; + int i, irqsafe = type != SAL_INFO_TYPE_MCA && type != SAL_INFO_TYPE_INIT; + int saved_size = ARRAY_SIZE(data->data_saved); + + BUG_ON(type >= ARRAY_SIZE(salinfo_log_name)); + + if (irqsafe) + spin_lock_irqsave(&data_saved_lock, flags); + for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) { + if (!data_saved->buffer) + break; + } + if (i == saved_size) { + if (!data->saved_num) { + shift1_data_saved(data, 0); + data_saved = data->data_saved + saved_size - 1; + } else + data_saved = NULL; + } + if (data_saved) { + data_saved->cpu = smp_processor_id(); + data_saved->id = ((sal_log_record_header_t *)buffer)->id; + data_saved->size = size; + data_saved->buffer = buffer; + } + if (irqsafe) + spin_unlock_irqrestore(&data_saved_lock, flags); + + if (!test_and_set_bit(smp_processor_id(), &data->cpu_event)) { + if (irqsafe) + up(&data->sem); + } +} + +static int +salinfo_event_open(struct inode *inode, struct file *file) +{ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + return 0; +} + +static ssize_t +salinfo_event_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +{ + struct inode *inode = file->f_dentry->d_inode; + struct proc_dir_entry *entry = PDE(inode); + struct salinfo_data *data = entry->data; + char cmd[32]; + size_t size; + int i, n, cpu = -1; + +retry: + if (down_trylock(&data->sem)) { + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + if (down_interruptible(&data->sem)) + return -ERESTARTSYS; + } + + n = data->cpu_check; + for (i = 0; i < NR_CPUS; i++) { + if (test_bit(n, &data->cpu_event)) { + cpu = n; + break; + } + if (++n == NR_CPUS) + n = 0; + } + + if (cpu == -1) + goto retry; + + /* events are sticky until the user says "clear" */ + up(&data->sem); + + /* for next read, start checking at next CPU */ + data->cpu_check = cpu; + if (++data->cpu_check == NR_CPUS) + data->cpu_check = 0; + + snprintf(cmd, sizeof(cmd), "read %d\n", cpu); + + size = strlen(cmd); + if (size > count) + size = count; + if (copy_to_user(buffer, cmd, size)) + return -EFAULT; + + return size; +} + +static struct file_operations salinfo_event_fops = { + .open = salinfo_event_open, + .read = salinfo_event_read, +}; + +static int +salinfo_log_open(struct inode *inode, struct file *file) +{ + struct proc_dir_entry *entry = PDE(inode); + struct salinfo_data *data = entry->data; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + spin_lock(&data_lock); + if (data->open) { + spin_unlock(&data_lock); + return -EBUSY; + } + data->open = 1; + spin_unlock(&data_lock); + + if (data->state == STATE_NO_DATA && + !(data->log_buffer = vmalloc(ia64_sal_get_state_info_size(data->type)))) { + data->open = 0; + return -ENOMEM; + } + + return 0; +} + +static int +salinfo_log_release(struct inode *inode, struct file *file) +{ + struct proc_dir_entry *entry = PDE(inode); + struct salinfo_data *data = entry->data; + + if (data->state == STATE_NO_DATA) { + vfree(data->log_buffer); + vfree(data->oemdata); + data->log_buffer = NULL; + data->oemdata = NULL; + } + spin_lock(&data_lock); + data->open = 0; + spin_unlock(&data_lock); + return 0; +} + +static void +call_on_cpu(int cpu, void (*fn)(void *), void *arg) +{ + cpumask_t save_cpus_allowed, new_cpus_allowed; + memcpy(&save_cpus_allowed, ¤t->cpus_allowed, sizeof(save_cpus_allowed)); + memset(&new_cpus_allowed, 0, sizeof(new_cpus_allowed)); + set_bit(cpu, &new_cpus_allowed); + set_cpus_allowed(current, new_cpus_allowed); + (*fn)(arg); + set_cpus_allowed(current, save_cpus_allowed); +} + +static void +salinfo_log_read_cpu(void *context) +{ + struct salinfo_data *data = context; + data->log_size = ia64_sal_get_state_info(data->type, (u64 *) data->log_buffer); +} + +static void +salinfo_log_new_read(int cpu, struct salinfo_data *data) +{ + struct salinfo_data_saved *data_saved; + unsigned long flags; + int i; + int saved_size = ARRAY_SIZE(data->data_saved); + + data->saved_num = 0; + spin_lock_irqsave(&data_saved_lock, flags); +retry: + for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) { + if (data_saved->buffer && data_saved->cpu == cpu) { + sal_log_record_header_t *rh = (sal_log_record_header_t *)(data_saved->buffer); + data->log_size = data_saved->size; + memcpy(data->log_buffer, rh, data->log_size); + barrier(); /* id check must not be moved */ + if (rh->id == data_saved->id) { + data->saved_num = i+1; + break; + } + /* saved record changed by mca.c since interrupt, discard it */ + shift1_data_saved(data, i); + goto retry; + } + } + spin_unlock_irqrestore(&data_saved_lock, flags); + + if (!data->saved_num) + call_on_cpu(cpu, salinfo_log_read_cpu, data); + data->state = data->log_size ? STATE_LOG_RECORD : STATE_NO_DATA; +} + +static ssize_t +salinfo_log_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +{ + struct inode *inode = file->f_dentry->d_inode; + struct proc_dir_entry *entry = PDE(inode); + struct salinfo_data *data = entry->data; + void *saldata; + size_t size; + u8 *buf; + u64 bufsize; + + if (data->state == STATE_LOG_RECORD) { + buf = data->log_buffer; + bufsize = data->log_size; + } else if (data->state == STATE_OEMDATA) { + buf = data->oemdata; + bufsize = data->oemdata_size; + } else { + buf = NULL; + bufsize = 0; + } + if (*ppos >= bufsize) + return 0; + + saldata = buf + file->f_pos; + size = bufsize - file->f_pos; + if (size > count) + size = count; + if (copy_to_user(buffer, saldata, size)) + return -EFAULT; + + *ppos += size; + return size; +} + +static void +salinfo_log_clear_cpu(void *context) +{ + struct salinfo_data *data = context; + ia64_sal_clear_state_info(data->type); +} + +static int +salinfo_log_clear(struct salinfo_data *data, int cpu) +{ + data->state = STATE_NO_DATA; + if (!test_bit(cpu, &data->cpu_event)) + return 0; + down(&data->sem); + clear_bit(cpu, &data->cpu_event); + if (data->saved_num) { + unsigned long flags; + spin_lock_irqsave(&data_saved_lock, flags); + shift1_data_saved(data, data->saved_num - 1 ); + data->saved_num = 0; + spin_unlock_irqrestore(&data_saved_lock, flags); + } + call_on_cpu(cpu, salinfo_log_clear_cpu, data); + + /* clearing a record may make a new record visible */ + salinfo_log_new_read(cpu, data); + if (data->state == STATE_LOG_RECORD && + !test_and_set_bit(cpu, &data->cpu_event)) + up(&data->sem); + return 0; +} + +static ssize_t +salinfo_log_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +{ + struct inode *inode = file->f_dentry->d_inode; + struct proc_dir_entry *entry = PDE(inode); + struct salinfo_data *data = entry->data; + char cmd[32]; + size_t size; + u32 offset; + int cpu; + + size = sizeof(cmd); + if (count < size) + size = count; + if (copy_from_user(cmd, buffer, size)) + return -EFAULT; + + if (sscanf(cmd, "read %d", &cpu) == 1) { + salinfo_log_new_read(cpu, data); + } else if (sscanf(cmd, "clear %d", &cpu) == 1) { + int ret; + if ((ret = salinfo_log_clear(data, cpu))) + count = ret; + } else if (sscanf(cmd, "oemdata %d %d", &cpu, &offset) == 2) { + if (data->state != STATE_LOG_RECORD && data->state != STATE_OEMDATA) + return -EINVAL; + if (offset > data->log_size - sizeof(efi_guid_t)) + return -EINVAL; + data->state = STATE_OEMDATA; + if (salinfo_platform_oemdata) { + struct salinfo_platform_oemdata_parms parms = { + .efi_guid = data->log_buffer + offset, + .oemdata = &data->oemdata, + .oemdata_size = &data->oemdata_size + }; + call_on_cpu(cpu, salinfo_platform_oemdata_cpu, &parms); + if (parms.ret) + count = parms.ret; + } else + data->oemdata_size = 0; + } else + return -EINVAL; + + return count; +} + +static struct file_operations salinfo_data_fops = { + .open = salinfo_log_open, + .release = salinfo_log_release, + .read = salinfo_log_read, + .write = salinfo_log_write, +}; static int __init salinfo_init(void) { struct proc_dir_entry *salinfo_dir; /* /proc/sal dir entry */ struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */ - int i; + struct proc_dir_entry *dir, *entry; + struct salinfo_data *data; + int i, j, online; salinfo_dir = proc_mkdir("sal", NULL); + if (!salinfo_dir) + return 0; for (i=0; i < NR_SALINFO_ENTRIES; i++) { /* pass the feature bit in question as misc data */ - *sdir = create_proc_read_entry (salinfo_entries[i].name, 0, salinfo_dir, + *sdir++ = create_proc_read_entry (salinfo_entries[i].name, 0, salinfo_dir, salinfo_read, (void *)salinfo_entries[i].feature); - if (*sdir) - (*sdir)->owner = THIS_MODULE; - sdir++; } - *sdir++ = salinfo_dir; - - return 0; -} -static void __exit -salinfo_exit(void) -{ - int i = 0; + for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) { + data = salinfo_data + i; + data->type = i; + sema_init(&data->sem, 0); + dir = proc_mkdir(salinfo_log_name[i], salinfo_dir); + if (!dir) + continue; + + entry = create_proc_entry("event", S_IRUSR, dir); + if (!entry) + continue; + entry->data = data; + entry->proc_fops = &salinfo_event_fops; + *sdir++ = entry; + + entry = create_proc_entry("data", S_IRUSR | S_IWUSR, dir); + if (!entry) + continue; + entry->data = data; + entry->proc_fops = &salinfo_data_fops; + *sdir++ = entry; + + /* we missed any events before now */ + online = 0; + for (j = 0; j < NR_CPUS; j++) + if (cpu_online(j)) { + set_bit(j, &data->cpu_event); + ++online; + } + sema_init(&data->sem, online); - for (i = 0; i < NR_SALINFO_ENTRIES ; i++) { - if (salinfo_proc_entries[i]) - remove_proc_entry (salinfo_proc_entries[i]->name, NULL); + *sdir++ = dir; } + + *sdir++ = salinfo_dir; + + return 0; } /* @@ -102,4 +584,3 @@ } module_init(salinfo_init); -module_exit(salinfo_exit); diff -Nru a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c --- a/arch/ia64/kernel/smpboot.c Sun Dec 21 00:13:14 2003 +++ b/arch/ia64/kernel/smpboot.c Sun Dec 21 00:13:14 2003 @@ -466,7 +466,7 @@ #ifdef CONFIG_NUMA /* on which node is each logical CPU (one cacheline even for 64 CPUs) */ -volatile char cpu_to_node_map[NR_CPUS] __cacheline_aligned; +volatile u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned; /* which logical CPUs are on which nodes */ volatile cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; diff -Nru a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S --- a/arch/ia64/kernel/vmlinux.lds.S Sun Dec 21 00:13:15 2003 +++ b/arch/ia64/kernel/vmlinux.lds.S Sun Dec 21 00:13:15 2003 @@ -151,7 +151,7 @@ { *(.con_initcall.init) } __con_initcall_end = .; __security_initcall_start = .; - .security_initcall.init : AT(ADDR(.security_initcall.init) - PAGE_OFFSET) + .security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { *(.security_initcall.init) } __security_initcall_end = .; . = ALIGN(PAGE_SIZE); diff -Nru a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile --- a/arch/ia64/lib/Makefile Sun Dec 21 00:13:15 2003 +++ b/arch/ia64/lib/Makefile Sun Dec 21 00:13:15 2003 @@ -13,6 +13,7 @@ lib-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o lib-$(CONFIG_PERFMON) += carta_random.o lib-$(CONFIG_MD_RAID5) += xor.o +lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o AFLAGS___divdi3.o = AFLAGS___udivdi3.o = -DUNSIGNED diff -Nru a/arch/ia64/lib/dec_and_lock.c b/arch/ia64/lib/dec_and_lock.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/lib/dec_and_lock.c Sun Dec 21 00:13:15 2003 @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2003 Jerome Marchand, Bull S.A. + * Cleaned up by David Mosberger-Tang + * + * This file is released under the GPLv2, or at your option any later version. + * + * ia64 version of "atomic_dec_and_lock()" using the atomic "cmpxchg" instruction. This + * code is an adaptation of the x86 version of "atomic_dec_and_lock()". + */ + +#include +#include +#include +#include + +/* + * Decrement REFCOUNT and if the count reaches zero, acquire the spinlock. Both of these + * operations have to be done atomically, so that the count doesn't drop to zero without + * acquiring the spinlock first. + */ +int +atomic_dec_and_lock (atomic_t *refcount, spinlock_t *lock) +{ + int old, new; + + do { + old = atomic_read(refcount); + new = old - 1; + + if (unlikely (old == 1)) { + /* oops, we may be decrementing to zero, do it the slow way... */ + spin_lock(lock); + if (atomic_dec_and_test(refcount)) + return 1; + spin_unlock(lock); + return 0; + } + } while (cmpxchg(&refcount->counter, old, new) != old); + return 0; +} + +EXPORT_SYMBOL(atomic_dec_and_lock); diff -Nru a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c --- a/arch/ia64/mm/discontig.c Sun Dec 21 00:13:15 2003 +++ b/arch/ia64/mm/discontig.c Sun Dec 21 00:13:15 2003 @@ -134,94 +134,69 @@ int node) { unsigned long epfn, cpu, cpus; - unsigned long pernodesize = 0, pernode; - void *cpu_data; + unsigned long pernodesize = 0, pernode, pages, mapsize; + void *cpu_data; struct bootmem_data *bdp = &mem_data[node].bootmem_data; epfn = (start + len) >> PAGE_SHIFT; + pages = bdp->node_low_pfn - (bdp->node_boot_start >> PAGE_SHIFT); + mapsize = bootmem_bootmap_pages(pages) << PAGE_SHIFT; + /* * Make sure this memory falls within this node's usable memory * since we may have thrown some away in build_maps(). */ - if (start < bdp->node_boot_start || - epfn > bdp->node_low_pfn) + if (start < bdp->node_boot_start || epfn > bdp->node_low_pfn) return 0; /* Don't setup this node's local space twice... */ - if (!mem_data[node].pernode_addr) { - /* - * Calculate total size needed, incl. what's necessary - * for good alignment and alias prevention. - */ - cpus = early_nr_cpus_node(node); - pernodesize += PERCPU_PAGE_SIZE * cpus; - pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t)); - pernodesize += L1_CACHE_ALIGN(sizeof(struct ia64_node_data)); - pernodesize = PAGE_ALIGN(pernodesize); - pernode = NODEDATA_ALIGN(start, node); - - /* Is this range big enough for what we want to store here? */ - if (start + len > (pernode + pernodesize)) { - mem_data[node].pernode_addr = pernode; - mem_data[node].pernode_size = pernodesize; - memset(__va(pernode), 0, pernodesize); - - cpu_data = (void *)pernode; - pernode += PERCPU_PAGE_SIZE * cpus; - - mem_data[node].pgdat = __va(pernode); - pernode += L1_CACHE_ALIGN(sizeof(pg_data_t)); - - mem_data[node].node_data = __va(pernode); - pernode += L1_CACHE_ALIGN(sizeof(struct ia64_node_data)); - - mem_data[node].pgdat->bdata = bdp; - pernode += L1_CACHE_ALIGN(sizeof(pg_data_t)); - - /* - * Copy the static per-cpu data into the region we - * just set aside and then setup __per_cpu_offset - * for each CPU on this node. - */ - for (cpu = 0; cpu < NR_CPUS; cpu++) { - if (node == node_cpuid[cpu].nid) { - memcpy(__va(cpu_data), __phys_per_cpu_start, - __per_cpu_end-__per_cpu_start); - __per_cpu_offset[cpu] = - (char*)__va(cpu_data) - - __per_cpu_start; - cpu_data += PERCPU_PAGE_SIZE; - } - } - } - } + if (mem_data[node].pernode_addr) + return 0; + + /* + * Calculate total size needed, incl. what's necessary + * for good alignment and alias prevention. + */ + cpus = early_nr_cpus_node(node); + pernodesize += PERCPU_PAGE_SIZE * cpus; + pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t)); + pernodesize += L1_CACHE_ALIGN(sizeof(struct ia64_node_data)); + pernodesize = PAGE_ALIGN(pernodesize); + pernode = NODEDATA_ALIGN(start, node); + + /* Is this range big enough for what we want to store here? */ + if (start + len > (pernode + pernodesize + mapsize)) { + mem_data[node].pernode_addr = pernode; + mem_data[node].pernode_size = pernodesize; + memset(__va(pernode), 0, pernodesize); + + cpu_data = (void *)pernode; + pernode += PERCPU_PAGE_SIZE * cpus; + + mem_data[node].pgdat = __va(pernode); + pernode += L1_CACHE_ALIGN(sizeof(pg_data_t)); - pernode = mem_data[node].pernode_addr; - pernodesize = mem_data[node].pernode_size; - if (pernode && !bdp->node_bootmem_map) { - unsigned long pages, mapsize, map = 0; - - pages = bdp->node_low_pfn - - (bdp->node_boot_start >> PAGE_SHIFT); - mapsize = bootmem_bootmap_pages(pages) << PAGE_SHIFT; + mem_data[node].node_data = __va(pernode); + pernode += L1_CACHE_ALIGN(sizeof(struct ia64_node_data)); + + mem_data[node].pgdat->bdata = bdp; + pernode += L1_CACHE_ALIGN(sizeof(pg_data_t)); /* - * The map will either contain the pernode area or begin - * after it. + * Copy the static per-cpu data into the region we + * just set aside and then setup __per_cpu_offset + * for each CPU on this node. */ - if (pernode - start > mapsize) - map = start; - else if (start + len - pernode - pernodesize > mapsize) - map = pernode + pernodesize; - - if (map) { - init_bootmem_node(mem_data[node].pgdat, - map>>PAGE_SHIFT, - bdp->node_boot_start>>PAGE_SHIFT, - bdp->node_low_pfn); + for (cpu = 0; cpu < NR_CPUS; cpu++) { + if (node == node_cpuid[cpu].nid) { + memcpy(__va(cpu_data), __phys_per_cpu_start, + __per_cpu_end - __per_cpu_start); + __per_cpu_offset[cpu] = (char*)__va(cpu_data) - + __per_cpu_start; + cpu_data += PERCPU_PAGE_SIZE; + } } - } return 0; @@ -314,6 +289,8 @@ */ void __init find_memory(void) { + int node; + reserve_memory(); if (numnodes == 0) { @@ -327,6 +304,31 @@ /* These actually end up getting called by call_pernode_memory() */ efi_memmap_walk(filter_rsvd_memory, build_node_maps); efi_memmap_walk(filter_rsvd_memory, find_pernode_space); + + /* + * Initialize the boot memory maps in reverse order since that's + * what the bootmem allocator expects + */ + for (node = numnodes - 1; node >= 0; node--) { + unsigned long pernode, pernodesize, map; + struct bootmem_data *bdp; + + bdp = &mem_data[node].bootmem_data; + pernode = mem_data[node].pernode_addr; + pernodesize = mem_data[node].pernode_size; + map = pernode + pernodesize; + + /* Sanity check... */ + if (!pernode) + panic("pernode space for node %d " + "could not be allocated!", node); + + init_bootmem_node(mem_data[node].pgdat, + map>>PAGE_SHIFT, + bdp->node_boot_start>>PAGE_SHIFT, + bdp->node_low_pfn); + } + efi_memmap_walk(filter_rsvd_memory, free_node_bootmem); reserve_pernode_space(); diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c --- a/arch/ia64/mm/init.c Sun Dec 21 00:13:14 2003 +++ b/arch/ia64/mm/init.c Sun Dec 21 00:13:14 2003 @@ -34,6 +34,7 @@ #include #include #include +#include DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -277,6 +278,10 @@ { unsigned long psr, pta, impl_va_bits; extern void __init tlb_init (void); +#ifdef CONFIG_IA64_MCA + int cpu; +#endif + #ifdef CONFIG_DISABLE_VHPT # define VHPT_ENABLE_BIT 0 #else @@ -335,6 +340,22 @@ ia64_set_pta(pta | (0 << 8) | (vmlpt_bits << 2) | VHPT_ENABLE_BIT); ia64_tlb_init(); + +#ifdef CONFIG_IA64_MCA + cpu = smp_processor_id(); + + /* mca handler uses cr.lid as key to pick the right entry */ + ia64_mca_tlb_list[cpu].cr_lid = ia64_getreg(_IA64_REG_CR_LID); + + /* insert this percpu data information into our list for MCA recovery purposes */ + ia64_mca_tlb_list[cpu].percpu_paddr = pte_val(mk_pte_phys(__pa(my_cpu_data), PAGE_KERNEL)); + /* Also save per-cpu tlb flush recipe for use in physical mode mca handler */ + ia64_mca_tlb_list[cpu].ptce_base = local_cpu_data->ptce_base; + ia64_mca_tlb_list[cpu].ptce_count[0] = local_cpu_data->ptce_count[0]; + ia64_mca_tlb_list[cpu].ptce_count[1] = local_cpu_data->ptce_count[1]; + ia64_mca_tlb_list[cpu].ptce_stride[0] = local_cpu_data->ptce_stride[0]; + ia64_mca_tlb_list[cpu].ptce_stride[1] = local_cpu_data->ptce_stride[1]; +#endif } #ifdef CONFIG_VIRTUAL_MEM_MAP diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c --- a/arch/ia64/pci/pci.c Sun Dec 21 00:13:14 2003 +++ b/arch/ia64/pci/pci.c Sun Dec 21 00:13:14 2003 @@ -153,7 +153,7 @@ res->end = end; res->flags = flags; - if (request_resource(root, res)) + if (insert_resource(root, res)) return -EBUSY; return 0; @@ -260,7 +260,6 @@ unsigned int windows = 0; char *name; - printk("PCI: Probing PCI hardware on bus (%04x:%02x)\n", domain, bus); controller = alloc_pci_controller(domain); if (!controller) goto out1; diff -Nru a/drivers/acpi/tables.c b/drivers/acpi/tables.c --- a/drivers/acpi/tables.c Sun Dec 21 00:13:14 2003 +++ b/drivers/acpi/tables.c Sun Dec 21 00:13:14 2003 @@ -262,10 +262,17 @@ /* Map the DSDT header via the pointer in the FADT */ if (id == ACPI_DSDT) { - struct acpi_table_fadt *fadt = (struct acpi_table_fadt *) *header; + struct fadt_descriptor_rev2 *fadt = (struct fadt_descriptor_rev2 *) *header; + + if (fadt->revision == 3 && fadt->Xdsdt) { + *header = (void *) __acpi_map_table(fadt->Xdsdt, + sizeof(struct acpi_table_header)); + } else if (fadt->V1_dsdt) { + *header = (void *) __acpi_map_table(fadt->V1_dsdt, + sizeof(struct acpi_table_header)); + } else + *header = 0; - *header = (void *) __acpi_map_table(fadt->dsdt_addr, - sizeof(struct acpi_table_header)); if (!*header) { printk(KERN_WARNING PREFIX "Unable to map DSDT\n"); return -ENODEV; diff -Nru a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile --- a/drivers/media/radio/Makefile Sun Dec 21 00:13:14 2003 +++ b/drivers/media/radio/Makefile Sun Dec 21 00:13:14 2003 @@ -2,6 +2,8 @@ # Makefile for the kernel character device drivers. # +obj-y := dummy.o + miropcm20-objs := miropcm20-rds-core.o miropcm20-radio.o obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o diff -Nru a/drivers/media/radio/dummy.c b/drivers/media/radio/dummy.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/radio/dummy.c Sun Dec 21 00:13:15 2003 @@ -0,0 +1 @@ +/* just so the linker knows what kind of object files it's deadling with... */ diff -Nru a/drivers/media/video/Makefile b/drivers/media/video/Makefile --- a/drivers/media/video/Makefile Sun Dec 21 00:13:14 2003 +++ b/drivers/media/video/Makefile Sun Dec 21 00:13:14 2003 @@ -7,6 +7,7 @@ zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o +obj-y := dummy.o obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o diff -Nru a/drivers/media/video/dummy.c b/drivers/media/video/dummy.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/video/dummy.c Sun Dec 21 00:13:15 2003 @@ -0,0 +1 @@ +/* just so the linker knows what kind of object files it's deadling with... */ diff -Nru a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c --- a/drivers/net/tulip/media.c Sun Dec 21 00:13:14 2003 +++ b/drivers/net/tulip/media.c Sun Dec 21 00:13:14 2003 @@ -278,6 +278,10 @@ for (i = 0; i < init_length; i++) outl(init_sequence[i], ioaddr + CSR12); } + + (void) inl(ioaddr + CSR6); /* flush CSR12 writes */ + udelay(500); /* Give MII time to recover */ + tmp_info = get_u16(&misc_info[1]); if (tmp_info) tp->advertising[phy_num] = tmp_info | 1; diff -Nru a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c --- a/drivers/serial/serial_core.c Sun Dec 21 00:13:14 2003 +++ b/drivers/serial/serial_core.c Sun Dec 21 00:13:14 2003 @@ -1862,6 +1862,9 @@ if (flow == 'r') termios.c_cflag |= CRTSCTS; + if (!port->ops) + return 0; + port->ops->set_termios(port, &termios, NULL); co->cflag = termios.c_cflag; diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c --- a/drivers/usb/serial/ipaq.c Sun Dec 21 00:13:15 2003 +++ b/drivers/usb/serial/ipaq.c Sun Dec 21 00:13:15 2003 @@ -222,7 +222,7 @@ * discipline instead of queueing. */ - port->tty->low_latency = 1; + port->tty->low_latency = 0; port->tty->raw = 1; port->tty->real_raw = 1; diff -Nru a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c --- a/fs/proc/task_mmu.c Sun Dec 21 00:13:14 2003 +++ b/fs/proc/task_mmu.c Sun Dec 21 00:13:14 2003 @@ -1,6 +1,7 @@ #include #include #include +#include #include char *task_mem(struct mm_struct *mm, char *buffer) @@ -75,6 +76,22 @@ return size; } +#ifdef AT_SYSINFO_EHDR + +static struct vm_area_struct gate_vmarea = { + /* Do _not_ mark this area as readable, cuz not the entire range may be readable + (e.g., due to execute-only pages or holes) and the tools that read + /proc/PID/maps should read the interesting bits from the gate-DSO file + instead. */ + .vm_start = FIXADDR_USER_START, + .vm_end = FIXADDR_USER_END +}; + +# define gate_map() &gate_vmarea +#else +# define gate_map() NULL +#endif + static int show_map(struct seq_file *m, void *v) { struct vm_area_struct *map = v; @@ -128,6 +145,8 @@ if (!map) { up_read(&mm->mmap_sem); mmput(mm); + if (l == -1) + map = gate_map(); } return map; } @@ -135,7 +154,7 @@ static void m_stop(struct seq_file *m, void *v) { struct vm_area_struct *map = v; - if (map) { + if (map && map != gate_map()) { struct mm_struct *mm = map->vm_mm; up_read(&mm->mmap_sem); mmput(mm); @@ -149,6 +168,8 @@ if (map->vm_next) return map->vm_next; m_stop(m, v); + if (map != gate_map()) + return gate_map(); return NULL; } diff -Nru a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h --- a/include/asm-ia64/acpi.h Sun Dec 21 00:13:15 2003 +++ b/include/asm-ia64/acpi.h Sun Dec 21 00:13:15 2003 @@ -88,11 +88,8 @@ const char *acpi_get_sysname (void); int acpi_request_vector (u32 int_type); -int acpi_get_prt (struct pci_vector_struct **vectors, int *count); -int acpi_get_interrupt_model (int *type); int acpi_register_irq (u32 gsi, u32 polarity, u32 trigger); int acpi_irq_to_vector (u32 irq); -int acpi_get_addr_space (void *obj, u8 type, u64 *base, u64 *length,u64 *tra); #ifdef CONFIG_ACPI_NUMA #include diff -Nru a/include/asm-ia64/intrinsics.h b/include/asm-ia64/intrinsics.h --- a/include/asm-ia64/intrinsics.h Sun Dec 21 00:13:14 2003 +++ b/include/asm-ia64/intrinsics.h Sun Dec 21 00:13:14 2003 @@ -167,7 +167,7 @@ if (_cmpxchg_bugcheck_count-- <= 0) { \ void *ip; \ extern int printk(const char *fmt, ...); \ - ip = ia64_getreg(_IA64_REG_IP); \ + ip = (void *) ia64_getreg(_IA64_REG_IP); \ printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v)); \ break; \ } \ diff -Nru a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h --- a/include/asm-ia64/mca.h Sun Dec 21 00:13:14 2003 +++ b/include/asm-ia64/mca.h Sun Dec 21 00:13:14 2003 @@ -18,6 +18,7 @@ #include #include #include +#include /* These are the return codes from all the IA64_MCA specific interfaces */ typedef int ia64_mca_return_code_t; @@ -61,6 +62,17 @@ IA64_MCA_RENDEZ_CHECKIN_DONE = 0x1 }; +/* the following data structure is used for TLB error recovery purposes */ +extern struct ia64_mca_tlb_info { + u64 cr_lid; + u64 percpu_paddr; + u64 ptce_base; + u32 ptce_count[2]; + u32 ptce_stride[2]; + u64 pal_paddr; + u64 pal_base; +} ia64_mca_tlb_list[NR_CPUS]; + /* Information maintained by the MC infrastructure */ typedef struct ia64_mc_info_s { u64 imi_mca_handler; @@ -141,7 +153,6 @@ extern int ia64_log_print(int,prfunc_t); extern void ia64_mca_cmc_vector_setup(void); extern int ia64_mca_check_errors(void); -extern u64 ia64_log_get(int, prfunc_t); #define PLATFORM_CALL(fn, args) printk("Platform call TBD\n") diff -Nru a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h --- a/include/asm-ia64/numa.h Sun Dec 21 00:13:14 2003 +++ b/include/asm-ia64/numa.h Sun Dec 21 00:13:14 2003 @@ -24,7 +24,7 @@ #include -extern volatile char cpu_to_node_map[NR_CPUS] __cacheline_aligned; +extern volatile u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned; extern volatile cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; /* Stuff below this line could be architecture independent */ diff -Nru a/include/asm-ia64/numnodes.h b/include/asm-ia64/numnodes.h --- a/include/asm-ia64/numnodes.h Sun Dec 21 00:13:15 2003 +++ b/include/asm-ia64/numnodes.h Sun Dec 21 00:13:15 2003 @@ -5,8 +5,8 @@ /* Max 8 Nodes */ #define NODES_SHIFT 3 #elif defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC) -/* Max 128 Nodes */ -#define NODES_SHIFT 7 +/* Max 256 Nodes */ +#define NODES_SHIFT 8 #endif #endif /* _ASM_MAX_NUMNODES_H */ diff -Nru a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h --- a/include/asm-ia64/pal.h Sun Dec 21 00:13:14 2003 +++ b/include/asm-ia64/pal.h Sun Dec 21 00:13:14 2003 @@ -461,23 +461,13 @@ } pal_processor_state_info_t; typedef struct pal_cache_check_info_s { - u64 reserved1 : 16, - way : 5, /* Way in which the - * error occurred - */ - reserved2 : 1, - mc : 1, /* Machine check corrected */ - tv : 1, /* Target address - * structure is valid - */ - - wv : 1, /* Way field valid */ - op : 3, /* Type of cache + u64 op : 4, /* Type of cache * operation that * caused the machine * check. */ - + level : 2, /* Cache level */ + reserved1 : 2, dl : 1, /* Failure in data part * of cache line */ @@ -486,11 +476,34 @@ */ dc : 1, /* Failure in dcache */ ic : 1, /* Failure in icache */ - index : 24, /* Cache line index */ - mv : 1, /* mesi valid */ mesi : 3, /* Cache line state */ - level : 4; /* Cache level */ + mv : 1, /* mesi valid */ + way : 5, /* Way in which the + * error occurred + */ + wiv : 1, /* Way field valid */ + reserved2 : 10, + + index : 20, /* Cache line index */ + reserved3 : 2, + is : 1, /* instruction set (1 == ia32) */ + iv : 1, /* instruction set field valid */ + pl : 2, /* privilege level */ + pv : 1, /* privilege level field valid */ + mcc : 1, /* Machine check corrected */ + tv : 1, /* Target address + * structure is valid + */ + rq : 1, /* Requester identifier + * structure is valid + */ + rp : 1, /* Responder identifier + * structure is valid + */ + pi : 1; /* Precise instruction pointer + * structure is valid + */ } pal_cache_check_info_t; typedef struct pal_tlb_check_info_s { @@ -498,18 +511,38 @@ u64 tr_slot : 8, /* Slot# of TR where * error occurred */ - reserved2 : 8, + trv : 1, /* tr_slot field is valid */ + reserved1 : 1, + level : 2, /* TLB level where failure occurred */ + reserved2 : 4, dtr : 1, /* Fail in data TR */ itr : 1, /* Fail in inst TR */ dtc : 1, /* Fail in data TC */ itc : 1, /* Fail in inst. TC */ - mc : 1, /* Machine check corrected */ - reserved1 : 43; + op : 4, /* Cache operation */ + reserved3 : 30, + is : 1, /* instruction set (1 == ia32) */ + iv : 1, /* instruction set field valid */ + pl : 2, /* privilege level */ + pv : 1, /* privilege level field valid */ + mcc : 1, /* Machine check corrected */ + tv : 1, /* Target address + * structure is valid + */ + rq : 1, /* Requester identifier + * structure is valid + */ + rp : 1, /* Responder identifier + * structure is valid + */ + pi : 1; /* Precise instruction pointer + * structure is valid + */ } pal_tlb_check_info_t; typedef struct pal_bus_check_info_s { - u64 size : 5, /* Xaction size*/ + u64 size : 5, /* Xaction size */ ib : 1, /* Internal bus error */ eb : 1, /* External bus error */ cc : 1, /* Error occurred @@ -518,22 +551,99 @@ */ type : 8, /* Bus xaction type*/ sev : 5, /* Bus error severity*/ - tv : 1, /* Targ addr valid */ - rp : 1, /* Resp addr valid */ - rq : 1, /* Req addr valid */ + hier : 2, /* Bus hierarchy level */ + reserved1 : 1, bsi : 8, /* Bus error status * info */ - mc : 1, /* Machine check corrected */ - reserved1 : 31; + reserved2 : 22, + + is : 1, /* instruction set (1 == ia32) */ + iv : 1, /* instruction set field valid */ + pl : 2, /* privilege level */ + pv : 1, /* privilege level field valid */ + mcc : 1, /* Machine check corrected */ + tv : 1, /* Target address + * structure is valid + */ + rq : 1, /* Requester identifier + * structure is valid + */ + rp : 1, /* Responder identifier + * structure is valid + */ + pi : 1; /* Precise instruction pointer + * structure is valid + */ } pal_bus_check_info_t; +typedef struct pal_reg_file_check_info_s { + u64 id : 4, /* Register file identifier */ + op : 4, /* Type of register + * operation that + * caused the machine + * check. + */ + reg_num : 7, /* Register number */ + rnv : 1, /* reg_num valid */ + reserved2 : 38, + + is : 1, /* instruction set (1 == ia32) */ + iv : 1, /* instruction set field valid */ + pl : 2, /* privilege level */ + pv : 1, /* privilege level field valid */ + mcc : 1, /* Machine check corrected */ + reserved3 : 3, + pi : 1; /* Precise instruction pointer + * structure is valid + */ +} pal_reg_file_check_info_t; + +typedef struct pal_uarch_check_info_s { + u64 sid : 5, /* Structure identification */ + level : 3, /* Level of failure */ + array_id : 4, /* Array identification */ + op : 4, /* Type of + * operation that + * caused the machine + * check. + */ + way : 6, /* Way of structure */ + wv : 1, /* way valid */ + xv : 1, /* index valid */ + reserved1 : 8, + index : 8, /* Index or set of the uarch + * structure that failed. + */ + reserved2 : 24, + + is : 1, /* instruction set (1 == ia32) */ + iv : 1, /* instruction set field valid */ + pl : 2, /* privilege level */ + pv : 1, /* privilege level field valid */ + mcc : 1, /* Machine check corrected */ + tv : 1, /* Target address + * structure is valid + */ + rq : 1, /* Requester identifier + * structure is valid + */ + rp : 1, /* Responder identifier + * structure is valid + */ + pi : 1; /* Precise instruction pointer + * structure is valid + */ +} pal_uarch_check_info_t; + typedef union pal_mc_error_info_u { u64 pmei_data; pal_processor_state_info_t pme_processor; pal_cache_check_info_t pme_cache; pal_tlb_check_info_t pme_tlb; pal_bus_check_info_t pme_bus; + pal_reg_file_check_info_t pme_reg_file; + pal_uarch_check_info_t pme_uarch; } pal_mc_error_info_t; #define pmci_proc_unknown_check pme_processor.uc diff -Nru a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h --- a/include/asm-ia64/pgtable.h Sun Dec 21 00:13:14 2003 +++ b/include/asm-ia64/pgtable.h Sun Dec 21 00:13:14 2003 @@ -230,6 +230,10 @@ #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) +/* This takes a physical page address that is used by the remapping functions */ +#define mk_pte_phys(physpage, pgprot) \ +({ pte_t __pte; pte_val(__pte) = physpage + pgprot_val(pgprot); __pte; }) + #define pte_modify(_pte, newprot) \ (__pte((pte_val(_pte) & ~_PAGE_CHG_MASK) | (pgprot_val(newprot) & _PAGE_CHG_MASK))) diff -Nru a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h --- a/include/asm-ia64/sal.h Sun Dec 21 00:13:15 2003 +++ b/include/asm-ia64/sal.h Sun Dec 21 00:13:15 2003 @@ -71,7 +71,9 @@ # define SAL_CALL_REENTRANT(result,args...) do { \ struct ia64_fpreg __ia64_scs_fr[6]; \ ia64_save_scratch_fpregs(__ia64_scs_fr); \ + preempt_disable(); \ __SAL_CALL(result, args); \ + preempt_enable(); \ ia64_load_scratch_fpregs(__ia64_scs_fr); \ } while (0) @@ -725,14 +727,16 @@ * Allow the OS to specify the interrupt number to be used by SAL to interrupt OS during * the machine check rendezvous sequence as well as the mechanism to wake up the * non-monarch processor at the end of machine check processing. + * Returns the complete ia64_sal_retval because some calls return more than just a status + * value. */ -static inline s64 +static inline struct ia64_sal_retval ia64_sal_mc_set_params (u64 param_type, u64 i_or_m, u64 i_or_m_val, u64 timeout, u64 rz_always) { struct ia64_sal_retval isrv; SAL_CALL(isrv, SAL_MC_SET_PARAMS, param_type, i_or_m, i_or_m_val, timeout, rz_always, 0, 0); - return isrv.status; + return isrv; } /* Read from PCI configuration space */ @@ -804,10 +808,12 @@ extern unsigned long sal_platform_features; +extern int (*salinfo_platform_oemdata)(const u8 *, u8 **, u64 *); + struct sal_ret_values { long r8; long r9; long r10; long r11; }; #endif /* __ASSEMBLY__ */ -#endif /* _ASM_IA64_PAL_H */ +#endif /* _ASM_IA64_SAL_H */ diff -Nru a/include/asm-ia64/spinlock.h b/include/asm-ia64/spinlock.h --- a/include/asm-ia64/spinlock.h Sun Dec 21 00:13:14 2003 +++ b/include/asm-ia64/spinlock.h Sun Dec 21 00:13:14 2003 @@ -39,7 +39,7 @@ { register volatile unsigned int *ptr asm ("r31") = &lock->lock; -#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) +#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3) # ifdef CONFIG_ITANIUM /* don't use brl on Itanium... */ asm volatile ("{\n\t" diff -Nru a/include/asm-ia64/system.h b/include/asm-ia64/system.h --- a/include/asm-ia64/system.h Sun Dec 21 00:13:14 2003 +++ b/include/asm-ia64/system.h Sun Dec 21 00:13:14 2003 @@ -19,8 +19,11 @@ #include #include -/* 0xa000000000000000 - 0xa000000000000000+PERCPU_PAGE_SIZE remain unmapped */ -#define GATE_ADDR (0xa000000000000000 + PERCPU_PAGE_SIZE) +#define GATE_ADDR (0xa000000000000000) +/* + * 0xa000000000000000+2*PERCPU_PAGE_SIZE + * - 0xa000000000000000+3*PERCPU_PAGE_SIZE remain unmapped (guard page) + */ #define KERNEL_START 0xa000000100000000 #define PERCPU_ADDR (-PERCPU_PAGE_SIZE) diff -Nru a/include/asm-ia64/uaccess.h b/include/asm-ia64/uaccess.h --- a/include/asm-ia64/uaccess.h Sun Dec 21 00:13:14 2003 +++ b/include/asm-ia64/uaccess.h Sun Dec 21 00:13:14 2003 @@ -50,7 +50,7 @@ #define get_fs() (current_thread_info()->addr_limit) #define set_fs(x) (current_thread_info()->addr_limit = (x)) -#define segment_eq(a,b) ((a).seg == (b).seg) +#define segment_eq(a, b) ((a).seg == (b).seg) /* * When accessing user memory, we need to make sure the entire area really is in @@ -58,16 +58,16 @@ * address TASK_SIZE is never valid. We also need to make sure that the address doesn't * point inside the virtually mapped linear page table. */ -#define __access_ok(addr,size,segment) \ - likely(((unsigned long) (addr)) <= (segment).seg \ - && ((segment).seg == KERNEL_DS.seg \ - || REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT)) -#define access_ok(type,addr,size) __access_ok((addr),(size),get_fs()) +#define __access_ok(addr, size, segment) \ + (likely((unsigned long) (addr) <= (segment).seg) \ + && ((segment).seg == KERNEL_DS.seg \ + || likely(REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT))) +#define access_ok(type, addr, size) __access_ok((addr), (size), get_fs()) static inline int verify_area (int type, const void *addr, unsigned long size) { - return access_ok(type,addr,size) ? 0 : -EFAULT; + return access_ok(type, addr, size) ? 0 : -EFAULT; } /* @@ -78,292 +78,173 @@ * (a) re-use the arguments for side effects (sizeof/typeof is ok) * (b) require any knowledge of processes at this stage */ -#define put_user(x,ptr) __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)),get_fs()) -#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)),get_fs()) +#define put_user(x, ptr) __put_user_check((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr)), get_fs()) +#define get_user(x, ptr) __get_user_check((x), (ptr), sizeof(*(ptr)), get_fs()) /* * The "__xxx" versions do not do address space checking, useful when * doing multiple accesses to the same area (the programmer has to do the * checks by hand with "access_ok()") */ -#define __put_user(x,ptr) __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) -#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr))) +#define __put_user(x, ptr) __put_user_nocheck((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr))) +#define __get_user(x, ptr) __get_user_nocheck((x), (ptr), sizeof(*(ptr))) #ifdef ASM_SUPPORTED - -extern void __get_user_unknown (void); - -#define __get_user_nocheck(x,ptr,size) \ -({ \ - register long __gu_err asm ("r8") = 0; \ - register long __gu_val asm ("r9") = 0; \ - switch (size) { \ - case 1: __get_user_8(ptr); break; \ - case 2: __get_user_16(ptr); break; \ - case 4: __get_user_32(ptr); break; \ - case 8: __get_user_64(ptr); break; \ - default: __get_user_unknown(); break; \ - } \ - (x) = (__typeof__(*(ptr))) __gu_val; \ - __gu_err; \ -}) - -#define __get_user_check(x,ptr,size,segment) \ -({ \ - register long __gu_err asm ("r8") = -EFAULT; \ - register long __gu_val asm ("r9") = 0; \ - const __typeof__(*(ptr)) *__gu_addr = (ptr); \ - if (__access_ok((long)__gu_addr,size,segment)) { \ - __gu_err = 0; \ - switch (size) { \ - case 1: __get_user_8(__gu_addr); break; \ - case 2: __get_user_16(__gu_addr); break; \ - case 4: __get_user_32(__gu_addr); break; \ - case 8: __get_user_64(__gu_addr); break; \ - default: __get_user_unknown(); break; \ - } \ - } \ - (x) = (__typeof__(*(ptr))) __gu_val; \ - __gu_err; \ -}) - -struct __large_struct { unsigned long buf[100]; }; -#define __m(x) (*(struct __large_struct *)(x)) + struct __large_struct { unsigned long buf[100]; }; +# define __m(x) (*(struct __large_struct *)(x)) /* We need to declare the __ex_table section before we can use it in .xdata. */ asm (".section \"__ex_table\", \"a\"\n\t.previous"); -#define __get_user_64(addr) \ - asm ("\n[1:]\tld8 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \ - "\t.xdata4 \"__ex_table\", 1b-., 1f-.+4\n" \ - "[1:]" \ - : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err)); - -#define __get_user_32(addr) \ - asm ("\n[1:]\tld4 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \ - "\t.xdata4 \"__ex_table\", 1b-., 1f-.+4\n" \ - "[1:]" \ - : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err)); - -#define __get_user_16(addr) \ - asm ("\n[1:]\tld2 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \ - "\t.xdata4 \"__ex_table\", 1b-., 1f-.+4\n" \ - "[1:]" \ - : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err)); - -#define __get_user_8(addr) \ - asm ("\n[1:]\tld1 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \ +# define __get_user_size(val, addr, n, err) \ +do { \ + register long __gu_r8 asm ("r8") = 0; \ + register long __gu_r9 asm ("r9"); \ + asm ("\n[1:]\tld"#n" %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \ "\t.xdata4 \"__ex_table\", 1b-., 1f-.+4\n" \ "[1:]" \ - : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err)); - -extern void __put_user_unknown (void); - -#define __put_user_nocheck(x,ptr,size) \ -({ \ - register long __pu_err asm ("r8") = 0; \ - switch (size) { \ - case 1: __put_user_8(x,ptr); break; \ - case 2: __put_user_16(x,ptr); break; \ - case 4: __put_user_32(x,ptr); break; \ - case 8: __put_user_64(x,ptr); break; \ - default: __put_user_unknown(); break; \ - } \ - __pu_err; \ -}) - -#define __put_user_check(x,ptr,size,segment) \ -({ \ - register long __pu_err asm ("r8") = -EFAULT; \ - __typeof__(*(ptr)) *__pu_addr = (ptr); \ - if (__access_ok((long)__pu_addr,size,segment)) { \ - __pu_err = 0; \ - switch (size) { \ - case 1: __put_user_8(x,__pu_addr); break; \ - case 2: __put_user_16(x,__pu_addr); break; \ - case 4: __put_user_32(x,__pu_addr); break; \ - case 8: __put_user_64(x,__pu_addr); break; \ - default: __put_user_unknown(); break; \ - } \ - } \ - __pu_err; \ -}) + : "=r"(__gu_r9), "=r"(__gu_r8) : "m"(__m(addr)), "1"(__gu_r8)); \ + (err) = __gu_r8; \ + (val) = __gu_r9; \ +} while (0) /* - * The "__put_user_xx()" macros tell gcc they read from memory - * instead of writing: this is because they do not write to - * any memory gcc knows about, so there are no aliasing issues + * The "__put_user_size()" macro tells gcc it reads from memory instead of writing it. This + * is because they do not write to any memory gcc knows about, so there are no aliasing + * issues. */ -#define __put_user_64(x,addr) \ - asm volatile ( \ - "\n[1:]\tst8 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \ - "\t.xdata4 \"__ex_table\", 1b-., 1f-.\n" \ - "[1:]" \ - : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) - -#define __put_user_32(x,addr) \ - asm volatile ( \ - "\n[1:]\tst4 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \ - "\t.xdata4 \"__ex_table\", 1b-., 1f-.\n" \ - "[1:]" \ - : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) - -#define __put_user_16(x,addr) \ - asm volatile ( \ - "\n[1:]\tst2 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \ - "\t.xdata4 \"__ex_table\", 1b-., 1f-.\n" \ - "[1:]" \ - : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) - -#define __put_user_8(x,addr) \ - asm volatile ( \ - "\n[1:]\tst1 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \ - "\t.xdata4 \"__ex_table\", 1b-., 1f-.\n" \ - "[1:]" \ - : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) +# define __put_user_size(val, addr, n, err) \ +do { \ + register long __pu_r8 asm ("r8") = 0; \ + asm volatile ("\n[1:]\tst"#n" %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \ + "\t.xdata4 \"__ex_table\", 1b-., 1f-.\n" \ + "[1:]" \ + : "=r"(__pu_r8) : "m"(__m(addr)), "rO"(val), "0"(__pu_r8)); \ + (err) = __pu_r8; \ +} while (0) #else /* !ASM_SUPPORTED */ - -#define RELOC_TYPE 2 /* ip-rel */ - -#define __put_user_xx(val, addr, size, err) \ - __st_user("__ex_table", (unsigned long) addr, size, RELOC_TYPE, (unsigned long) (val)); \ - (err) = ia64_getreg(_IA64_REG_R8); - -#define __get_user_xx(val, addr, size, err) \ - __ld_user("__ex_table", (unsigned long) addr, size, RELOC_TYPE); \ - (err) = ia64_getreg(_IA64_REG_R8); \ - (val) = ia64_getreg(_IA64_REG_R9); +# define RELOC_TYPE 2 /* ip-rel */ +# define __get_user_size(val, addr, n, err) \ +do { \ + __ld_user("__ex_table", (unsigned long) addr, n, RELOC_TYPE); \ + (err) = ia64_getreg(_IA64_REG_R8); \ + (val) = ia64_getreg(_IA64_REG_R9); \ +} while (0) +# define __put_user_size(val, addr, n, err) \ +do { \ + __st_user("__ex_table", (unsigned long) addr, n, RELOC_TYPE, (unsigned long) (val)); \ + (err) = ia64_getreg(_IA64_REG_R8); \ +} while (0) +#endif /* !ASM_SUPPORTED */ extern void __get_user_unknown (void); -#define __get_user_nocheck(x, ptr, size) \ -({ \ - register long __gu_err = 0; \ - register long __gu_val = 0; \ - const __typeof__(*(ptr)) *__gu_addr = (ptr); \ - switch (size) { \ - case 1: case 2: case 4: case 8: \ - __get_user_xx(__gu_val, __gu_addr, size, __gu_err); \ - break; \ - default: \ - __get_user_unknown(); \ - break; \ - } \ - (x) = (__typeof__(*(ptr))) __gu_val; \ - __gu_err; \ +/* + * Evaluating arguments X, PTR, SIZE, and SEGMENT may involve subroutine-calls, which + * could clobber r8 and r9 (among others). Thus, be careful not to evaluate it while + * using r8/r9. + */ +#define __do_get_user(check, x, ptr, size, segment) \ +({ \ + const __typeof__(*(ptr)) *__gu_ptr = (ptr); \ + __typeof__ (size) __gu_size = (size); \ + long __gu_err = -EFAULT, __gu_val = 0; \ + \ + if (!check || __access_ok((long) __gu_ptr, size, segment)) \ + switch (__gu_size) { \ + case 1: __get_user_size(__gu_val, __gu_ptr, 1, __gu_err); break; \ + case 2: __get_user_size(__gu_val, __gu_ptr, 2, __gu_err); break; \ + case 4: __get_user_size(__gu_val, __gu_ptr, 4, __gu_err); break; \ + case 8: __get_user_size(__gu_val, __gu_ptr, 8, __gu_err); break; \ + default: __get_user_unknown(); break; \ + } \ + (x) = (__typeof__(*(__gu_ptr))) __gu_val; \ + __gu_err; \ }) -#define __get_user_check(x,ptr,size,segment) \ -({ \ - register long __gu_err = -EFAULT; \ - register long __gu_val = 0; \ - const __typeof__(*(ptr)) *__gu_addr = (ptr); \ - if (__access_ok((long) __gu_addr, size, segment)) { \ - switch (size) { \ - case 1: case 2: case 4: case 8: \ - __get_user_xx(__gu_val, __gu_addr, size, __gu_err); \ - break; \ - default: \ - __get_user_unknown(); break; \ - } \ - } \ - (x) = (__typeof__(*(ptr))) __gu_val; \ - __gu_err; \ -}) +#define __get_user_nocheck(x, ptr, size) __do_get_user(0, x, ptr, size, KERNEL_DS) +#define __get_user_check(x, ptr, size, segment) __do_get_user(1, x, ptr, size, segment) extern void __put_user_unknown (void); -#define __put_user_nocheck(x, ptr, size) \ -({ \ - int __pu_err = 0; \ - __typeof__(*(ptr)) *__pu_addr = (ptr); \ - switch (size) { \ - case 1: case 2: case 4: case 8: \ - __put_user_xx(x, __pu_addr, size, __pu_err); \ - break; \ - default: \ - __put_user_unknown(); break; \ - } \ - __pu_err; \ -}) - -#define __put_user_check(x,ptr,size,segment) \ -({ \ - register long __pu_err = -EFAULT; \ - __typeof__(*(ptr)) *__pu_addr = (ptr); \ - if (__access_ok((long)__pu_addr,size,segment)) { \ - switch (size) { \ - case 1: case 2: case 4: case 8: \ - __put_user_xx(x,__pu_addr, size, __pu_err); \ - break; \ - default: \ - __put_user_unknown(); break; \ - } \ - } \ - __pu_err; \ +/* + * Evaluating arguments X, PTR, SIZE, and SEGMENT may involve subroutine-calls, which + * could clobber r8 (among others). Thus, be careful not to evaluate them while using r8. + */ +#define __do_put_user(check, x, ptr, size, segment) \ +({ \ + __typeof__ (x) __pu_x = (x); \ + __typeof__ (*(ptr)) *__pu_ptr = (ptr); \ + __typeof__ (size) __pu_size = (size); \ + long __pu_err = -EFAULT; \ + \ + if (!check || __access_ok((long) __pu_ptr, __pu_size, segment)) \ + switch (__pu_size) { \ + case 1: __put_user_size(__pu_x, __pu_ptr, 1, __pu_err); break; \ + case 2: __put_user_size(__pu_x, __pu_ptr, 2, __pu_err); break; \ + case 4: __put_user_size(__pu_x, __pu_ptr, 4, __pu_err); break; \ + case 8: __put_user_size(__pu_x, __pu_ptr, 8, __pu_err); break; \ + default: __put_user_unknown(); break; \ + } \ + __pu_err; \ }) -#endif /* !ASM_SUPPORTED */ +#define __put_user_nocheck(x, ptr, size) __do_put_user(0, x, ptr, size, KERNEL_DS) +#define __put_user_check(x, ptr, size, segment) __do_put_user(1, x, ptr, size, segment) /* * Complex access routines */ extern unsigned long __copy_user (void *to, const void *from, unsigned long count); -#define __copy_to_user(to,from,n) __copy_user((to), (from), (n)) -#define __copy_from_user(to,from,n) __copy_user((to), (from), (n)) +#define __copy_to_user(to, from, n) __copy_user((to), (from), (n)) +#define __copy_from_user(to, from, n) __copy_user((to), (from), (n)) -#define copy_to_user(to,from,n) __copy_tofrom_user((to), (from), (n), 1) -#define copy_from_user(to,from,n) __copy_tofrom_user((to), (from), (n), 0) +#define copy_to_user(to, from, n) __copy_tofrom_user((to), (from), (n), 1) +#define copy_from_user(to, from, n) __copy_tofrom_user((to), (from), (n), 0) -#define __copy_tofrom_user(to,from,n,check_to) \ -({ \ - void *__cu_to = (to); \ - const void *__cu_from = (from); \ - long __cu_len = (n); \ - \ - if (__access_ok((long) ((check_to) ? __cu_to : __cu_from), __cu_len, get_fs())) { \ - __cu_len = __copy_user(__cu_to, __cu_from, __cu_len); \ - } \ - __cu_len; \ +#define __copy_tofrom_user(to, from, n, check_to) \ +({ \ + void *__cu_to = (to); \ + const void *__cu_from = (from); \ + long __cu_len = (n); \ + \ + if (__access_ok((long) ((check_to) ? __cu_to : __cu_from), __cu_len, get_fs())) \ + __cu_len = __copy_user(__cu_to, __cu_from, __cu_len); \ + __cu_len; \ }) -#define __copy_in_user(to, from, size) \ - __copy_user((to), (from), (size)) +#define __copy_in_user(to, from, size) __copy_user((to), (from), (size)) static inline unsigned long copy_in_user (void *to, const void *from, unsigned long n) { - if (likely(access_ok(VERIFY_READ, from, n) && - access_ok(VERIFY_WRITE, to, n))) + if (likely(access_ok(VERIFY_READ, from, n) && access_ok(VERIFY_WRITE, to, n))) n = __copy_user(to, from, n); return n; } extern unsigned long __do_clear_user (void *, unsigned long); -#define __clear_user(to,n) \ -({ \ - __do_clear_user(to,n); \ -}) +#define __clear_user(to, n) __do_clear_user(to, n) -#define clear_user(to,n) \ +#define clear_user(to, n) \ ({ \ unsigned long __cu_len = (n); \ - if (__access_ok((long) to, __cu_len, get_fs())) { \ + if (__access_ok((long) to, __cu_len, get_fs())) \ __cu_len = __do_clear_user(to, __cu_len); \ - } \ __cu_len; \ }) -/* Returns: -EFAULT if exception before terminator, N if the entire - buffer filled, else strlen. */ - +/* + * Returns: -EFAULT if exception before terminator, N if the entire buffer filled, else + * strlen. + */ extern long __strncpy_from_user (char *to, const char *from, long to_len); -#define strncpy_from_user(to,from,n) \ +#define strncpy_from_user(to, from, n) \ ({ \ const char * __sfu_from = (from); \ long __sfu_ret = -EFAULT; \ diff -Nru a/include/linux/module.h b/include/linux/module.h --- a/include/linux/module.h Sun Dec 21 00:13:15 2003 +++ b/include/linux/module.h Sun Dec 21 00:13:15 2003 @@ -60,10 +60,11 @@ #define __module_cat(a,b) ___module_cat(a,b) #define __MODULE_INFO(tag, name, info) \ static const char __module_cat(name,__LINE__)[] \ + __attribute_used__ \ __attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info -#define MODULE_GENERIC_TABLE(gtype,name) \ -extern const struct gtype##_id __mod_##gtype##_table \ +#define MODULE_GENERIC_TABLE(gtype,name) \ +extern const struct gtype##_id __mod_##gtype##_table \ __attribute__ ((unused, alias(__stringify(name)))) #define THIS_MODULE (&__this_module) @@ -142,6 +143,7 @@ #define __CRC_SYMBOL(sym, sec) \ extern void *__crc_##sym __attribute__((weak)); \ static const unsigned long __kcrctab_##sym \ + __attribute_used__ \ __attribute__((section("__kcrctab" sec), unused)) \ = (unsigned long) &__crc_##sym; #else @@ -155,6 +157,7 @@ __attribute__((section("__ksymtab_strings"))) \ = MODULE_SYMBOL_PREFIX #sym; \ static const struct kernel_symbol __ksymtab_##sym \ + __attribute_used__ \ __attribute__((section("__ksymtab" sec), unused)) \ = { (unsigned long)&sym, __kstrtab_##sym } diff -Nru a/include/linux/moduleparam.h b/include/linux/moduleparam.h --- a/include/linux/moduleparam.h Sun Dec 21 00:13:14 2003 +++ b/include/linux/moduleparam.h Sun Dec 21 00:13:14 2003 @@ -52,6 +52,7 @@ #define __module_param_call(prefix, name, set, get, arg, perm) \ static char __param_str_##name[] __initdata = prefix #name; \ static struct kernel_param const __param_##name \ + __attribute_used__ \ __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ = { __param_str_##name, perm, set, get, arg } diff -Nru a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h --- a/include/linux/nfs_fs.h Sun Dec 21 00:13:14 2003 +++ b/include/linux/nfs_fs.h Sun Dec 21 00:13:14 2003 @@ -403,7 +403,7 @@ nfs_size_to_loff_t(__u64 size) { loff_t maxsz = (((loff_t) ULONG_MAX) << PAGE_CACHE_SHIFT) + PAGE_CACHE_SIZE - 1; - if (size > maxsz) + if (size > (__u64) maxsz) return maxsz; return (loff_t) size; } diff -Nru a/kernel/printk.c b/kernel/printk.c --- a/kernel/printk.c Sun Dec 21 00:13:15 2003 +++ b/kernel/printk.c Sun Dec 21 00:13:15 2003 @@ -361,6 +361,12 @@ __call_console_drivers(start, end); } } +#ifdef CONFIG_IA64_EARLY_PRINTK + if (!console_drivers) { + void early_printk (const char *str, size_t len); + early_printk(&LOG_BUF(start), end - start); + } +#endif } /* @@ -678,7 +684,11 @@ * for us. */ spin_lock_irqsave(&logbuf_lock, flags); +#ifdef CONFIG_IA64_EARLY_PRINTK + con_start = log_end; +#else con_start = log_start; +#endif spin_unlock_irqrestore(&logbuf_lock, flags); } release_console_sem(); @@ -731,3 +741,117 @@ tty->driver->write(tty, 0, msg, strlen(msg)); return; } + +#ifdef CONFIG_IA64_EARLY_PRINTK + +#include + +# ifdef CONFIG_IA64_EARLY_PRINTK_VGA + + +#define VGABASE ((char *)0xc0000000000b8000) +#define VGALINES 24 +#define VGACOLS 80 + +static int current_ypos = VGALINES, current_xpos = 0; + +static void +early_printk_vga (const char *str, size_t len) +{ + char c; + int i, k, j; + + while (len-- > 0) { + c = *str++; + if (current_ypos >= VGALINES) { + /* scroll 1 line up */ + for (k = 1, j = 0; k < VGALINES; k++, j++) { + for (i = 0; i < VGACOLS; i++) { + writew(readw(VGABASE + 2*(VGACOLS*k + i)), + VGABASE + 2*(VGACOLS*j + i)); + } + } + for (i = 0; i < VGACOLS; i++) { + writew(0x720, VGABASE + 2*(VGACOLS*j + i)); + } + current_ypos = VGALINES-1; + } + if (c == '\n') { + current_xpos = 0; + current_ypos++; + } else if (c != '\r') { + writew(((0x7 << 8) | (unsigned short) c), + VGABASE + 2*(VGACOLS*current_ypos + current_xpos++)); + if (current_xpos >= VGACOLS) { + current_xpos = 0; + current_ypos++; + } + } + } +} + +# endif /* CONFIG_IA64_EARLY_PRINTK_VGA */ + +# ifdef CONFIG_IA64_EARLY_PRINTK_UART + +#include +#include + +static void early_printk_uart(const char *str, size_t len) +{ + static char *uart = NULL; + unsigned long uart_base; + char c; + + if (!uart) { + uart_base = 0; +# ifdef CONFIG_SERIAL_8250_HCDP + { + extern unsigned long hcdp_early_uart(void); + uart_base = hcdp_early_uart(); + } +# endif +# if CONFIG_IA64_EARLY_PRINTK_UART_BASE + if (!uart_base) + uart_base = CONFIG_IA64_EARLY_PRINTK_UART_BASE; +# endif + if (!uart_base) + return; + + uart = ioremap(uart_base, 64); + if (!uart) + return; + } + + while (len-- > 0) { + c = *str++; + while ((readb(uart + UART_LSR) & UART_LSR_TEMT) == 0) + cpu_relax(); /* spin */ + + writeb(c, uart + UART_TX); + + if (c == '\n') + writeb('\r', uart + UART_TX); + } +} + +# endif /* CONFIG_IA64_EARLY_PRINTK_UART */ + +#ifdef CONFIG_IA64_EARLY_PRINTK_SGI_SN +extern int early_printk_sn_sal(const char *str, int len); +#endif + +void early_printk(const char *str, size_t len) +{ +#ifdef CONFIG_IA64_EARLY_PRINTK_UART + early_printk_uart(str, len); +#endif +#ifdef CONFIG_IA64_EARLY_PRINTK_VGA + early_printk_vga(str, len); +#endif +#ifdef CONFIG_IA64_EARLY_PRINTK_SGI_SN + early_printk_sn_sal(str, len); +#endif +} + +#endif /* CONFIG_IA64_EARLY_PRINTK */ diff -Nru a/mm/memory.c b/mm/memory.c --- a/mm/memory.c Sun Dec 21 00:13:14 2003 +++ b/mm/memory.c Sun Dec 21 00:13:14 2003 @@ -121,8 +121,12 @@ } pmd = pmd_offset(dir, 0); pgd_clear(dir); - for (j = 0; j < PTRS_PER_PMD ; j++) - free_one_pmd(tlb, pmd+j); + for (j = 0; j < PTRS_PER_PMD - PREFETCH_STRIDE/sizeof(*pmd); ++j) { + prefetchw(pmd + j + PREFETCH_STRIDE/sizeof(*pmd)); + free_one_pmd(tlb, pmd + j); + } + for (; j < PTRS_PER_PMD; j++) + free_one_pmd(tlb, pmd + j); pmd_free_tlb(tlb, pmd); }