diff -uNr --exclude=CVS linux-2.4.8-ac9/Documentation/Configure.help linuxppc64_2_4/Documentation/Configure.help --- linux-2.4.8-ac9/Documentation/Configure.help Thu Aug 23 09:17:13 2001 +++ linuxppc64_2_4/Documentation/Configure.help Thu Aug 23 10:25:17 2001 @@ -179,6 +179,14 @@ from Motorola. The Linux PowerPC port has a home page at . +PowerPC64 processor +CONFIG_PPC64 + The PowerPC architecture was designed for both 32 bit and 64 bit + processor implementations. 64 bit PowerPC processors are in many + ways a superset of their 32 bit PowerPC cousins. Each 64 bit PowerPC + processor also has a 32 bit mode to allow for 32 bit compatibility. + The home of the PowerPC 64 Linux project is at + Motorola 68K processors CONFIG_M68K The Motorola 68K microprocessors are now obsolete, having been @@ -19876,30 +19884,70 @@ machines: Apple Power Macintoshes and clones (such as the Motorola Starmax series), PReP (PowerPC Reference Platform) machines such as the Motorola PowerStack, CHRP (Common Hardware Reference Platform), - the embedded MBX boards from Motorola and many others. Currently, + the embedded MBX boards from Motorola and many others. Currently, the default option is to build a kernel which works on the first three. Support for other machines is currently incomplete. Select PowerMac/PReP/MTX/CHRP if configuring for any of the above. Select Gemini if configuring for a Synergy Microsystems' Gemini - series Single Board Computer. More information is available at: - . + series Single Board Computer. More information is available at: + + + Select APUS if configuring for a PowerUP Amiga. More information is + available at: + +# Choice: i or p +Platform support +CONFIG_PPC_ISERIES + Linux runs on certain models of the IBM AS/400, now known as the + IBM iSeries. Generally if you can run LPAR (Logical Partitioning) + on your iSeries you can run Linux in a partition on your machine. + + Linux also runs on most models of IBM pSeries hardware. (pSeries + used to be known as the RS/6000) + + If you have an iSeries and want to run Linux in a partition, + select the iSeries option to build your kernel. + + If you have a pSeries and want to run Linux, select pSeries + as the option to build your kernel. + + See for exact model information to see what + can run the 64 bit PowerPC kernel. - Select APUS if configuring for a PowerUP Amiga. More information is - available at: . + iSeries Linux information from IBM can be found at: + + + pSeries Linux information from IBM can be found at: + + + Project information can be found at: + + + +Platform support +CONFIG_PPC_PSERIES + Linux runs on most models of IBM pSeries hardware. (pSeries used + to be known as the RS/6000) + + See for exact model information for the + 64 bit PowerPC kernel. + + pSeries Linux information from IBM can be found at: + Synergy-Gemini CONFIG_GEMINI Select Gemini if configuring for a Synergy Microsystems' Gemini series Single Board Computer. More information is available at: - . + Amiga-Apus CONFIG_APUS Select APUS if configuring for a PowerUP Amiga. More information is available at: - . + Power management support for PowerBooks CONFIG_PMAC_PBOOK @@ -20095,26 +20143,33 @@ Support for EST8260 CONFIG_EST8260 The EST8260 is a single-board computer manufactured by Wind River - Systems, Inc. (formerly Embedded Support Tools Corp.) and based on - the MPC8260. Wind River Systems has a website at - , but the EST8260 cannot be found on it + Systems Inc. (formerly Embedded Support Tools Corp.) and based + on the MPC8260. Wind River Systems has a website at + , but the EST8260 cannot be found on it and has probably been discontinued or rebadged. +Support for Large Memory +CONFIG_MSCHUNKS + MsChunks stands for Main Store Chunks and specifically allows the + 64 bit PowerPC Linux kernel to optimize for machines with sparce + discontiguous memory. iSeries kernels need to have this on. + It is recommended that for pSeries hardware that you answer Y. + AltiVec support CONFIG_ALTIVEC Say Y here to compile in support for Motorola AltiVec boards. The - AltiVec board is baced on the MPC7400 embedded version of the - PowerPC and adds a SIMD vector-processing unit. Product information + AltiVec board is baced on the MPC7400 embedded version of the + PowerPC and adds a SIMD vector-processing unit. Product information at . ADB raw keycode support CONFIG_MAC_ADBKEYCODES This provides support for sending raw ADB keycodes to console devices. This is the default up to 2.4.0, but in future this may be - phased out in favor of generic Linux keycodes. If you say Y here, + phased out in favor of generic Linux keycodes. If you say Y here, you can dynamically switch via the /proc/sys/dev/mac_hid/keyboard_sends_linux_keycodes - sysctl and with the "keyboard_sends_linux_keycodes=" kernel + sysctl and with the "keyboard_sends_linux_keycodes=" kernel argument. If unsure, say Y here. @@ -20122,8 +20177,8 @@ Mouse button 2+3 emulation support CONFIG_MAC_EMUMOUSEBTN This provides generic support for emulating the 2nd and 3rd mouse - button with keypresses. If you say Y here, the emulation is still - disabled by default. The emulation is controlled by these sysctl + button with keypresses. If you say Y here, the emulation is still + disabled by default. The emulation is controlled by these sysctl entries: /proc/sys/dev/mac_hid/mouse_button_emulation /proc/sys/dev/mac_hid/mouse_button2_keycode @@ -22836,6 +22891,11 @@ CONFIG_XMON Include in-kernel hooks for the xmon kernel monitor/debugger supported by the PPC port. + +Include realtime debugging +CONFIG_PPCDBG + Include in-kernel PowerPC 64 information hooks that may be turned on/off + in real time. Include kgdb kernel debugger CONFIG_KWDB diff -uNr --exclude=CVS linux-2.4.8-ac9/MAINTAINERS linuxppc64_2_4/MAINTAINERS --- linux-2.4.8-ac9/MAINTAINERS Thu Aug 23 09:17:14 2001 +++ linuxppc64_2_4/MAINTAINERS Thu Aug 23 10:25:17 2001 @@ -863,14 +863,10 @@ S: Maintained LINUX FOR 64BIT POWERPC -P: Tom Gall -M: tom_gall@vnet.ibm.com P: David Engebretsen M: engebret@us.ibm.com -P: Dwayne McConnell -M: dwayne@austin.ibm.com W: http://linuxppc64.org -L: linuxppc64-dev@lists.linuxppc.porg +L: linuxppc64-dev@lists.linuxppc.org S: Supported LOGICAL VOLUME MANAGER diff -uNr --exclude=CVS linux-2.4.8-ac9/Makefile linuxppc64_2_4/Makefile --- linux-2.4.8-ac9/Makefile Thu Aug 23 09:17:14 2001 +++ linuxppc64_2_4/Makefile Thu Aug 23 10:25:17 2001 @@ -10,11 +10,13 @@ # SUBARCH tells the usermode build what the underlying arch is. That is set # first, and if a usermode build is happening, the "ARCH=um" on the command # line overrides the setting of ARCH below. If a native build is happening, -# then ARCH is assigned, getting whatever value it gets normally, and +# then ARCH is assigned, getting whatever value it gets normally, and # SUBARCH is subsequently ignored. SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) -ARCH := $(SUBARCH) +#ARCH := $(SUBARCH) + +ARCH := ppc64 CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ else if [ -x /bin/bash ]; then echo /bin/bash; \ @@ -27,7 +29,7 @@ HOSTCC = gcc HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -CROSS_COMPILE = +CROSS_COMPILE = /usr/local/ppc64-current3.0/bin/powerpc64-linux- # # Include the make variables (CC, etc...) @@ -97,7 +99,7 @@ CPPFLAGS := -D__KERNEL__ -I$(HPATH) CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \ - -fomit-frame-pointer -fno-strict-aliasing -fno-common + -fomit-frame-pointer -fno-strict-aliasing -fno-common AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS) # diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/Makefile linuxppc64_2_4/arch/ppc64/Makefile --- linux-2.4.8-ac9/arch/ppc64/Makefile Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/Makefile Thu Aug 23 16:45:14 2001 @@ -19,13 +19,19 @@ CHECKS = checks endif +# Re: -DPPC64_32B_ADDR_SPACE in CPPLAGS/CFLAGS below. +# For 64-bit apps, temporarily reduce the size of the address space +# available to user application. This allow us to use strace without +# having to compile a strace64 program. This shouldn't affect anyone +# other than Steve Munroe, Peter Bergner. I will back this hack out +# later... -Peter + ASFLAGS = LINKFLAGS = -T arch/ppc64/vmlinux.lds -Ttext $(KERNELLOAD) -Bstatic -CPPFLAGS := $(CPPFLAGS) -D__powerpc__ -include $(TOPDIR)/arch/ppc64/mymacros.h -CFLAGS := $(CFLAGS) -D__linux__ -D__powerpc__ -fsigned-char -Wa,-Saix \ +CPPFLAGS := $(CPPFLAGS) -D__powerpc__ -DPPC64_32B_ADDR_SPACE +CFLAGS := $(CFLAGS) -D__linux__ -D__powerpc__ -fsigned-char \ -msoft-float -pipe -Wno-uninitialized $(PRINTK) \ - -include $(TOPDIR)/arch/ppc64/mymacros.h -mminimal-toc \ - -fno-builtin + -mminimal-toc -fno-builtin -DPPC64_32B_ADDR_SPACE CPP = $(CC) -E $(CFLAGS) @@ -52,8 +58,7 @@ BOOT_TARGETS = zImage znetboot.initrd zImage.initrd -ifdef CONFIG_POWER3 -ifndef CONFIG_8260 +ifdef CONFIG_PPC_PSERIES $(BOOT_TARGETS): $(CHECKS) vmlinux @$(MAKEBOOT) $@ @@ -62,23 +67,9 @@ ifdef CONFIG_SMP cp -f vmlinux /tftpboot/vmlinux.smp else - cp -f vmlinux /tftpboot/vmlinux -endif -endif - @$(MAKEBOOT) $@ -else -# 8260 is custom 6xx -$(BOOT_TARGETS): $(CHECKS) vmlinux - @$(MAKEMBXBOOT) $@ + cp -f vmlinux /tftpboot/vmlinux.smp.64 endif endif - -ifdef CONFIG_PPC64BRIDGE -$(BOOT_TARGETS): $(CHECKS) vmlinux - @$(MAKEBOOT) $@ - -znetboot: $(CHECKS) vmlinux - cp -f vmlinux /tftpboot/vmlinux.64 @$(MAKEBOOT) $@ endif diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/boot/Makefile linuxppc64_2_4/arch/ppc64/boot/Makefile --- linux-2.4.8-ac9/arch/ppc64/boot/Makefile Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/boot/Makefile Thu Aug 16 14:57:25 2001 @@ -18,7 +18,7 @@ # compile for 32bit mode. BOOTCC = $(HOSTCC) -BOOTCFLAGS = $(HOSTCFLAGS) +BOOTCFLAGS = $(HOSTCFLAGS) -I$(HPATH) BOOTLD = ld BOOTAS = as BOOTAFLAGS = -D__ASSEMBLY__ $(HOSTCFLAGS) diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/config.in linuxppc64_2_4/arch/ppc64/config.in --- linux-2.4.8-ac9/arch/ppc64/config.in Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/config.in Thu Aug 23 19:48:56 2001 @@ -9,59 +9,23 @@ mainmenu_name "64 bit PowerPC Linux Kernel Configuration" mainmenu_option next_comment -comment 'Code maturity level options' -bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL + comment 'Code maturity level options' + bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL endmenu mainmenu_option next_comment comment 'Platform support' define_bool CONFIG_PPC y define_bool CONFIG_PPC64 y -choice 'Processor Type' \ - "IStar CONFIG_ISTAR \ - iSeries CONFIG_PPC_ISERIES \ - POWER3 CONFIG_POWER3 \ - POWER4 CONFIG_POWER4 " POWER3 +define_bool CONFIG_ALL_PPC y +define_bool CONFIG_SERIAL_CONSOLE y - -if [ "$CONFIG_ISTAR" = "y" -o "$CONFIG_POWER4" = "y" ]; then - define_bool CONFIG_SERIAL_CONSOLE y -fi - - -if [ "$CONFIG_8xx" = "y" ]; then - define_bool CONFIG_SERIAL_CONSOLE y - - choice 'Machine Type' \ - "RPX-Lite CONFIG_RPXLITE \ - RPX-Classic CONFIG_RPXCLASSIC \ - BSE-IP CONFIG_BSEIP \ - MBX CONFIG_MBX \ - WinCept CONFIG_WINCEPT" RPX-Lite -fi -if [ "$CONFIG_6xx" = "y" ]; then - choice 'Machine Type' \ - "PowerMac/PReP/MTX/CHRP CONFIG_ALL_PPC \ - Gemini CONFIG_GEMINI \ - EST8260 CONFIG_EST8260 \ - APUS CONFIG_APUS" PowerMac/PReP/MTX/CHRP -fi - -if [ "$CONFIG_POWER3" = "y" ]; then - define_bool CONFIG_ALL_PPC y -fi - -if [ "$CONFIG_POWER4" = "y" ]; then - define_bool CONFIG_ALL_PPC y -fi - -if [ "$CONFIG_ISTAR" = "y" ]; then - define_bool CONFIG_ALL_PPC y -fi +choice 'Machine Type' \ + "pSeries CONFIG_PPC_PSERIES \ + iSeries CONFIG_PPC_ISERIES" CONFIG_PPC_PSERIES if [ "$CONFIG_PPC_ISERIES" = "y" ]; then - define_bool CONFIG_ALL_PPC y - define_bool CONFIG_MSCHUNKS y + define_bool CONFIG_MSCHUNKS y fi bool 'Symmetric multi-processing support' CONFIG_SMP @@ -83,11 +47,9 @@ define_bool CONFIG_ISA n define_bool CONFIG_SBUS n - -#Too many -o's for menuconfig -#if [ "$CONFIG_POWER3" = "y" -o "$CONFIG_POWER4" = "y" -o "$CONFIG_ISTAR" ="y"]; then - define_bool CONFIG_PCI y -#fi +define_bool CONFIG_MCA n +define_bool CONFIG_EISA n +define_bool CONFIG_PCI y bool 'Networking support' CONFIG_NET bool 'Sysctl support' CONFIG_SYSCTL @@ -99,17 +61,9 @@ define_bool CONFIG_KCORE_ELF y fi -#Commented By Adam. We must ask the question. Interactivity is the key :-) -#define_bool CONFIG_BINFMT_ELF y -#define_bool CONFIG_KERNEL_ELF y //WHAT IS THIS???// - bool 'Kernel Support for 64 bit ELF binaries' CONFIG_BINFMT_ELF - -#Too many -o 's for menuconfig -#if [ "$CONFIG_POWER3" = "y" -o "$CONFIG_POWER4" = "y"-o"$CONFIG_ISTAR"="y"]; then tristate 'Kernel support for 32 bit binaries' CONFIG_BINFMT_ELF32 -#fi tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC @@ -125,24 +79,11 @@ source drivers/parport/Config.in - if [ "$CONFIG_PPC_ISERIES" != "y" ]; then - if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then - bool 'Support for VGA Console' CONFIG_VGA_CONSOLE - bool 'Support for frame buffer devices' CONFIG_FB - if [ "$CONFIG_FB" = "y" ]; then - bool 'Backward compatibility mode for Xpmac' CONFIG_FB_COMPAT_XPMAC - fi - - bool 'Power management support for PowerBooks' CONFIG_PMAC_PBOOK - tristate 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL - if [ "$CONFIG_MAC_SERIAL" = "y" ]; then - bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE - fi - bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE - bool 'Support for early boot text console (BootX only)' CONFIG_BOOTX_TEXT - bool 'Support for Motorola Hot Swap' CONFIG_MOTOROLA_HOTSWAP - fi + bool 'Support for VGA Console' CONFIG_VGA_CONSOLE + bool 'Support for frame buffer devices' CONFIG_FB + + bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE fi endmenu @@ -153,44 +94,34 @@ source drivers/md/Config.in if [ "$CONFIG_NET" = "y" ]; then - source net/Config.in + source net/Config.in fi -mainmenu_option next_comment -comment 'ATA/IDE/MFM/RLL support' - -tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE - -if [ "$CONFIG_IDE" != "n" ]; then - source drivers/ide/Config.in -else - define_bool CONFIG_BLK_DEV_IDE_MODES n - define_bool CONFIG_BLK_DEV_HD n -fi -endmenu +define_bool CONFIG_BLK_DEV_IDE_MODES n +define_bool CONFIG_BLK_DEV_HD n mainmenu_option next_comment comment 'SCSI support' tristate 'SCSI support' CONFIG_SCSI if [ "$CONFIG_SCSI" != "n" ]; then - source drivers/scsi/Config.in + source drivers/scsi/Config.in fi endmenu source drivers/ieee1394/Config.in if [ "$CONFIG_NET" = "y" ]; then - mainmenu_option next_comment - comment 'Network device support' + mainmenu_option next_comment + comment 'Network device support' - bool 'Network device support' CONFIG_NETDEVICES - if [ "$CONFIG_NETDEVICES" = "y" ]; then - source drivers/net/Config.in - if [ "$CONFIG_ATM" = "y" ]; then - source drivers/atm/Config.in - fi - fi - endmenu + bool 'Network device support' CONFIG_NETDEVICES + if [ "$CONFIG_NETDEVICES" = "y" ]; then + source drivers/net/Config.in + if [ "$CONFIG_ATM" = "y" ]; then + source drivers/atm/Config.in + fi + fi + endmenu fi source net/ax25/Config.in @@ -202,7 +133,7 @@ tristate 'ISDN support' CONFIG_ISDN if [ "$CONFIG_ISDN" != "n" ]; then - source drivers/isdn/Config.in + source drivers/isdn/Config.in fi endmenu @@ -211,7 +142,7 @@ bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then - source drivers/cdrom/Config.in + source drivers/cdrom/Config.in fi endmenu @@ -227,16 +158,12 @@ comment 'Sound' tristate 'Sound card support' CONFIG_SOUND if [ "$CONFIG_SOUND" != "n" ]; then - source drivers/sound/dmasound/Config.in - source drivers/sound/Config.in + source drivers/sound/dmasound/Config.in + source drivers/sound/Config.in fi endmenu -if [ "$CONFIG_8260" = "y" ]; then -source arch/ppc/8260_io/Config.in -fi - source drivers/usb/Config.in mainmenu_option next_comment @@ -245,10 +172,10 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ bool 'Include kgdb kernel debugger' CONFIG_KGDB bool 'Include xmon kernel debugger' CONFIG_XMON -bool 'Include kdb kernel debugger' CONFIG_KDB -if [ "$CONFIG_KDB" = "y" ]; then - bool ' KDB off by default' CONFIG_KDB_OFF - define_bool CONFIG_KALLSYMS y -fi +#bool 'Include kdb kernel debugger' CONFIG_KDB +#if [ "$CONFIG_KDB" = "y" ]; then +# bool ' KDB off by default' CONFIG_KDB_OFF +# define_bool CONFIG_KALLSYMS y +#fi bool 'Include PPCDBG realtime debugging' CONFIG_PPCDBG endmenu diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/defconfig linuxppc64_2_4/arch/ppc64/defconfig --- linux-2.4.8-ac9/arch/ppc64/defconfig Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/defconfig Mon Aug 20 14:07:04 2001 @@ -1,5 +1,5 @@ # -# Automatically generated make config: don't edit +# Automatically generated by make menuconfig: don't edit # # CONFIG_UID16 is not set # CONFIG_RWSEM_GENERIC_SPINLOCK is not set @@ -15,13 +15,12 @@ # CONFIG_PPC=y CONFIG_PPC64=y -# CONFIG_ISTAR is not set -# CONFIG_PPC_ISERIES is not set -CONFIG_POWER3=y -# CONFIG_POWER4 is not set CONFIG_ALL_PPC=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_PPC_ISERIES is not set +CONFIG_PPC_PSERIES=y CONFIG_SMP=y -# CONFIG_MSCHUNKS is not set +CONFIG_MSCHUNKS=y # # Loadable module support @@ -33,6 +32,8 @@ # # CONFIG_ISA is not set # CONFIG_SBUS is not set +# CONFIG_MCA is not set +# CONFIG_EISA is not set CONFIG_PCI=y CONFIG_NET=y CONFIG_SYSCTL=y @@ -50,13 +51,9 @@ # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_VGA_CONSOLE=y +# CONFIG_VGA_CONSOLE is not set CONFIG_FB=y -# CONFIG_FB_COMPAT_XPMAC is not set -# CONFIG_PMAC_PBOOK is not set -# CONFIG_MAC_SERIAL is not set -CONFIG_PROC_DEVICETREE=y -# CONFIG_BOOTX_TEXT is not set +# CONFIG_PROC_DEVICETREE is not set # CONFIG_MOTOROLA_HOTSWAP is not set # @@ -75,7 +72,6 @@ # Block devices # CONFIG_BLK_DEV_FD=y -# CONFIG_VIODASD is not set # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set @@ -121,10 +117,6 @@ # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set # CONFIG_ATM is not set - -# -# -# # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_DECNET is not set @@ -154,10 +146,6 @@ # SCSI support # CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# CONFIG_BLK_DEV_SD=y CONFIG_SD_EXTRA_DEVS=40 CONFIG_CHR_DEV_ST=y @@ -166,10 +154,6 @@ CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_SR_EXTRA_DEVS=2 CONFIG_CHR_DEV_SG=y - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# # CONFIG_SCSI_DEBUG_QUEUES is not set # CONFIG_SCSI_MULTI_LUN is not set # CONFIG_SCSI_CONSTANTS is not set @@ -186,6 +170,7 @@ # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set @@ -414,7 +399,6 @@ # CONFIG_SERIAL_NONSTANDARD is not set CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 -# CONFIG_VIOCONS is not set # # I2C support @@ -441,10 +425,6 @@ # CONFIG_INPUT_EMU10K1 is not set # CONFIG_INPUT_SERIO is not set # CONFIG_INPUT_SERPORT is not set - -# -# Joysticks -# # CONFIG_INPUT_ANALOG is not set # CONFIG_INPUT_A3D is not set # CONFIG_INPUT_ADI is not set @@ -540,6 +520,7 @@ # Network File Systems # # CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_ROOT_NFS is not set @@ -618,17 +599,9 @@ # USB support # # CONFIG_USB is not set - -# -# USB Controllers -# # CONFIG_USB_UHCI is not set # CONFIG_USB_UHCI_ALT is not set # CONFIG_USB_OHCI is not set - -# -# USB Device Class drivers -# # CONFIG_USB_AUDIO is not set # CONFIG_USB_BLUETOOTH is not set # CONFIG_USB_STORAGE is not set @@ -638,48 +611,28 @@ # CONFIG_USB_STORAGE_SDDR09 is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set - -# -# USB Human Interface Devices (HID) -# # CONFIG_USB_HID is not set # CONFIG_USB_HIDDEV is not set # CONFIG_USB_KBD is not set # CONFIG_USB_MOUSE is not set # CONFIG_USB_WACOM is not set - -# -# USB Imaging devices -# # CONFIG_USB_DC2XX is not set # CONFIG_USB_MDC800 is not set # CONFIG_USB_SCANNER is not set # CONFIG_USB_MICROTEK is not set # CONFIG_USB_HP5300 is not set - -# -# USB Multimedia devices -# # CONFIG_USB_IBMCAM is not set # CONFIG_USB_OV511 is not set # CONFIG_USB_PWC is not set # CONFIG_USB_SE401 is not set # CONFIG_USB_DSBR is not set # CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# # CONFIG_USB_PLUSB is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_KAWETH is not set # CONFIG_USB_CATC is not set # CONFIG_USB_CDCETHER is not set # CONFIG_USB_USBNET is not set - -# -# USB port drivers -# # CONFIG_USB_USS720 is not set # @@ -707,10 +660,6 @@ # CONFIG_USB_SERIAL_PL2303 is not set # CONFIG_USB_SERIAL_CYBERJACK is not set # CONFIG_USB_SERIAL_OMNINET is not set - -# -# Miscellaneous USB drivers -# # CONFIG_USB_RIO500 is not set # @@ -719,5 +668,4 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_KGDB is not set CONFIG_XMON=y -# CONFIG_KDB is not set CONFIG_PPCDBG=y diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/HvLpConfig.c linuxppc64_2_4/arch/ppc64/kernel/HvLpConfig.c --- linux-2.4.8-ac9/arch/ppc64/kernel/HvLpConfig.c Wed Dec 31 18:00:00 1969 +++ linuxppc64_2_4/arch/ppc64/kernel/HvLpConfig.c Tue Aug 21 22:09:44 2001 @@ -0,0 +1,63 @@ +/* + * HvLpConfig.c + * Copyright (C) 2001 Kyle A. Lucke, IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _HVLPCONFIG_H +#include +#endif + +HvLpIndex HvLpConfig_getLpIndex_outline(void) +{ + return HvLpConfig_getLpIndex(); +} + +const HvLpIndexMap HvLpIndexMapDefault = (1 << (sizeof(HvLpIndexMap) * 8 - 1)); +const HvLpIndex HvHardcodedPrimaryLpIndex = 0; +const HvLpIndex HvMaxArchitectedLps = HVMAXARCHITECTEDLPS; +const HvLpVirtualLanIndex HvMaxArchitectedVirtualLans = 16; +const HvLpSharedPoolIndex HvMaxArchitectedSharedPools = 16; +const HvLpSharedPoolIndex HvMaxSupportedSharedPools = 1; +const HvLpIndex HvMaxRuntimeLpsPreCondor = 12; +const HvLpIndex HvMaxRuntimeLps = HVMAXARCHITECTEDLPS; +const HvLpIndex HvLpIndexInvalid = 0xff; +const u16 HvInvalidProcIndex = 0xffff; +const u32 HvVirtualFlashSize = 0x200; +const u32 HvMaxBusesPreCondor = 32; +const u32 HvMaxBusesCondor = 256; +const u32 HvMaxArchitectedBuses = 512; +const HvLpBus HvCspBusNumber = 1; +const u32 HvMaxSanHwSets = 16; +const HvLpCard HvMaxSystemIops = 200; +const HvLpCard HvMaxBusIops = 20; +const u16 HvMaxUnitsPerIop = 100; +const u64 HvPageSize = 4 * 1024; +const u64 HvChunkSize = HVCHUNKSIZE; +const u64 HvChunksPerMeg = HVCHUNKSPERMEG; +const u64 HvPagesPerChunk = HVPAGESPERCHUNK; +const u64 HvPagesPerMeg = HVPAGESPERMEG; +const u64 HvLpMinMegsPrimary = HVLPMINMEGSPRIMARY; +const u64 HvLpMinMegsSecondary = HVLPMINMEGSSECONDARY; +const u64 HvLpMinChunksPrimary = HVLPMINMEGSPRIMARY * HVCHUNKSPERMEG; +const u64 HvLpMinChunksSecondary = HVLPMINMEGSSECONDARY * HVCHUNKSPERMEG; +const u64 HvLpMinPagesPrimary = HVLPMINMEGSPRIMARY * HVPAGESPERMEG; +const u64 HvLpMinPagesSecondary = HVLPMINMEGSSECONDARY * HVPAGESPERMEG; +const u8 HvLpMinProcs = 1; +const u8 HvLpConfigMinInteract = 1; +const u16 HvLpMinSharedProcUnitsX100 = 10; +const u16 HvLpMaxSharedProcUnitsX100 = 100; +const HvLpSharedPoolIndex HvLpSharedPoolIndexInvalid = 0xff; diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/Makefile linuxppc64_2_4/arch/ppc64/kernel/Makefile --- linux-2.4.8-ac9/arch/ppc64/kernel/Makefile Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/kernel/Makefile Tue Aug 14 23:13:12 2001 @@ -26,12 +26,12 @@ ioctl32.o ptrace32.o signal32.o open_pic.o xics.o \ pmc.o mf_proc.o proc_pmc.o iSeries_setup.o \ ItLpQueue.o hvCall.o mf.o viopath.o HvLpEvent.o \ - iSeries_proc.o HvCall.o flight_recorder.o + iSeries_proc.o HvCall.o flight_recorder.o HvLpConfig.o obj-$(CONFIG_PCI) += pci.o ifeq ($(CONFIG_PPC_ISERIES),y) -obj-$(CONFIG_PCI) += iSeries_dma.o iSeries_rtc.o +obj-$(CONFIG_PCI) += iSeries_dma.o iSeries_rtc.o proc_pcifr.o else obj-$(CONFIG_PCI) += pci_dma.o proc_pcifr.o endif diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/entry.S linuxppc64_2_4/arch/ppc64/kernel/entry.S --- linux-2.4.8-ac9/arch/ppc64/kernel/entry.S Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/kernel/entry.S Fri Aug 24 07:02:12 2001 @@ -306,10 +306,10 @@ mtmsrd r6 /* Update machine state */ ld r6,_MSR(r1) - mtspr SRR0,r7 - mtspr SRR1,r6 ld r2,GPR2(r1) ld r1,GPR1(r1) + mtspr SRR0,r7 + mtspr SRR1,r6 /* sync required to force memory operations on this processor */ /* to complete before the current thread gives up control. */ @@ -334,33 +334,20 @@ ld r5,_MSR(r1) andi. r5,r5,MSR_EE beq 2f - -_GLOBAL(lost_irq_ret) -3: LOADBASE(r4,ppc_n_lost_interrupts) - lwz r4,ppc_n_lost_interrupts@l(r4) - cmpi 0,r4,0 - bne- 1f /* do_IRQ if lost interrupts */ +irq_recheck: + mfmsr r5 + andi. r5,r5,MSR_EE + bne 4f /* - * Check for pending I/O events (iSeries) - * If no I/O events pending then CR0 = "eq" and r4 = 0 - * (kills registers r5 and r6) + * Check for pending interrupts (iSeries) */ - CHECKLPQUEUE(r4,r5,r6) - beq+ 4f /* skip do_IRQ if no events */ -1: + CHECKANYINT(r4,r5) + beq+ 4f /* skip do_IRQ if no interrupts */ + addi r3,r1,STACK_FRAME_OVERHEAD bl .do_IRQ - b 3b /* loop back and handle more */ + b irq_recheck /* loop back and handle more */ 4: - /* - * Check for lost decrementer interrupts. - * (If decrementer popped while we were in the hypervisor) - */ - CHECKDECR(r4,r5) - beq+ 5f - addi r3,r1,STACK_FRAME_OVERHEAD - bl .timer_interrupt -5: LOADADDR(r4,irq_stat) #ifdef CONFIG_SMP /* get processor # */ @@ -388,7 +375,6 @@ /* NEED_RESCHED is a volatile long (64-bits) */ mfspr r4,SPRG3 /* current task's PACA */ ld r4,PACACURRENT(r4) /* Get 'current' */ - ld r3,NEED_RESCHED(r4) cmpi 0,r3,0 /* check need_resched flag */ beq+ 7f @@ -423,17 +409,26 @@ rldicl r0,r0,48,1 rldicl r0,r0,16,0 /* clear MSR_EE */ mtmsrd r0 /* Update machine state */ + + ld r0,_MSR(r1) + andi. r3,r0,MSR_EE + beq+ 1f + + CHECKANYINT(r4,r3) + bne- irq_recheck - /* if returning to user mode, set new sprg3 and save kernel SP */ +1: + stdcx. r0,0,r1 /* to clear the reservation */ + + /* if returning to user mode, save kernel SP */ ld r0,_MSR(r1) andi. r0,r0,MSR_PR beq+ 1f addi r0,r1,INT_FRAME_SIZE /* size of frame */ mfspr r4,SPRG3 /* current task's PACA */ - ld r4,PACACURRENT(r4) /* Get 'current' */ - std r0,THREAD+KSP(r4) /* save kernel stack pointer */ - mfspr r2,SPRG3 /* Get Paca */ - std r1,PACAKSAVE(r2) /* save exception stack pointer */ + ld r2,PACACURRENT(r4) /* Get 'current' */ + std r0,THREAD+KSP(r2) /* save kernel stack pointer */ + std r1,PACAKSAVE(r4) /* save exception stack pointer */ 1: ld r0,_MSR(r1) mtspr SRR1,r0 diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/head.S linuxppc64_2_4/arch/ppc64/kernel/head.S --- linux-2.4.8-ac9/arch/ppc64/kernel/head.S Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/kernel/head.S Fri Aug 24 07:02:12 2001 @@ -26,6 +26,8 @@ * */ +#define SECONDARY_PROCESSORS + #include "ppc_asm.h" #include "ppc_defs.h" #include @@ -326,22 +328,32 @@ .globl SystemReset_Iseries SystemReset_Iseries: - mfspr r3,SPRG3 /* Get Paca address */ - lhz r24,PACAPACAINDEX(r3) /* Get processor # */ + mfspr 25,SPRG3 /* Get Paca address */ + lhz r24,PACAPACAINDEX(r25) /* Get processor # */ cmpi 0,r24,0 /* Are we processor 0? */ beq .__start_initialization_iSeries /* Start up the first processor */ mfspr r4,CTRLF li r5,RUNLATCH /* Turn off the run light */ andc r4,r4,r5 mtspr CTRLT,r4 + 1: HMT_LOW #ifdef CONFIG_SMP - lbz r23,PACAPROCSTART(r3) /* Test if this processor + lbz r23,PACAPROCSTART(r25) /* Test if this processor * should start */ + sync + LOADADDR(r3,current_set) + sldi r28,r24,4 /* get current_set[cpu#] */ + ldx r3,r3,r28 + addi r1,r3,TASK_UNION_SIZE + subi r1,r1,STACK_FRAME_OVERHEAD + cmpi 0,r23,0 beq iseries_secondary_smp_loop /* Loop until told to go */ +#ifdef SECONDARY_PROCESSORS bne .__secondary_start /* Loop until told to go */ +#endif iseries_secondary_smp_loop: /* Let the Hypervisor know we are alive */ /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ @@ -354,13 +366,13 @@ which are running on multi-threaded machines. */ lis r3,0x8000 rldicr r3,r3,32,15 /* r3 = (r3 << 32) & 0xffff000000000000 */ - addi r3,r3,18 /* r3 = -x8000000000000012 which is "yield" */ + addi r3,r3,18 /* r3 = 0x8000000000000012 which is "yield" */ li r4,0 /* "yield timed" */ li r5,-1 /* "yield forever" */ #endif /* CONFIG_SMP */ li r0,-1 /* r0=-1 indicates a Hypervisor call */ sc /* Invoke the hypervisor via a system call */ - mfspr r3,SPRG3 /* Put r3 back */ + mfspr r25,SPRG3 /* Put r25 back ???? */ b 1b /* If SMP not configured, secondaries * loop forever */ @@ -368,7 +380,6 @@ STD_EXCEPTION_COMMON( 0x100, SystemReset, .SystemResetException ) STD_EXCEPTION_COMMON( 0x200, MachineCheck, .MachineCheckException ) - STD_EXCEPTION_COMMON( 0x500, HardwareInterrupt, .do_IRQ ) STD_EXCEPTION_COMMON( 0x900, Decrementer, .timer_interrupt ) STD_EXCEPTION_COMMON( 0xa00, Trap_0a, .UnknownException ) STD_EXCEPTION_COMMON( 0xb00, Trap_0b, .UnknownException ) @@ -376,8 +387,21 @@ STD_EXCEPTION_COMMON( 0xe00, Trap_0e, .UnknownException ) STD_EXCEPTION_COMMON( 0xf00, PerformanceMonitor, .PerformanceMonitorException ) +/* r20 is in SPRG2, + r21 is in the PACA +*/ .globl DataAccess_common DataAccess_common: + mfcr r20 + mfspr r21,DAR + srdi r21,r21,60 + cmpi 0,r21,0xc + bne 3f + + /* Segment faulted on a bolted segment. Go off and map that segment. */ + b .do_stab_bolted + +3: mtcr r20 EXCEPTION_PROLOG_COMMON mfspr r20,DSISR std r20,_DSISR(r21) @@ -520,6 +544,17 @@ .llong .do_page_fault .llong .ret_from_except + .globl HardwareInterrupt_common +HardwareInterrupt_common: + EXCEPTION_PROLOG_COMMON +HardwareInterrupt_entry: + addi r3,r1,STACK_FRAME_OVERHEAD + SET_REG_TO_CONST(r20, MSR_KERNEL) + li r6,0x500 + bl .transfer_to_handler + .llong .do_IRQ + .llong .ret_from_except + .globl Alignment_common Alignment_common: EXCEPTION_PROLOG_COMMON @@ -559,6 +594,11 @@ .globl SystemCall_common SystemCall_common: EXCEPTION_PROLOG_COMMON + cmpi 0,r0,0x5555 /* Special syscall to handle pending */ + bne+ 1f /* interrupts */ + andi. r6,r23,MSR_PR /* Only allowed from kernel */ + beq+ HardwareInterrupt_entry +1: std r3,ORIG_GPR3(r21) SET_REG_TO_CONST(r20, MSR_KERNEL) rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ @@ -612,6 +652,124 @@ ld r21,GPR21(r21) rfid +/* orig r20 is in SPRG2, + orig r21 is in the PACA + r20 contains CCR + + r22 needs to be saved + r1 needs to be saved + CCR needs to be saved +*/ +_GLOBAL(do_stab_bolted) + mfsprg r21,3 + std r22,PACAR22(r21) + std r1,PACAR1(r21) + stw r20,PACACCR(r21) + mfspr r21,DAR + + /* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */ + rldicl r20,r21,36,32 /* Permits a full 32b of ESID */ + rldicr r20,r20,15,48 + rldicl r21,r21,4,60 + or r20,r20,r21 + + li r21,9 /* VSID_RANDOMIZER */ + rldicr r21,r21,32,31 + oris r21,r21,58231 + ori r21,r21,39831 + + mulld r20,r20,r21 + clrldi r20,r20,28 /* r20 = vsid */ + + mfsprg r21,3 + ld r21,PACASTABVIRT(r21) + + /* Hash to the primary group */ + mfspr r22,DAR + rldicl r22,r22,36,59 + rldicr r22,r22,7,56 + or r21,r21,r22 /* r21 = first ste of the group */ + + /* Search the primary group for a free entry */ + li r22,0 +1: + ld r1,0(r21) /* Test valid bit of the current ste */ + rldicl r1,r1,57,63 + cmpwi r1,0 + bne 2f + ld r1,8(r21) /* Get the current vsid part of the ste */ + rldimi r1,r20,12,0 /* Insert the new vsid value */ + std r1,8(r21) /* Put new entry back into the stab */ + eieio /* Order vsid update */ + ld r1,0(r21) /* Get the esid part of the ste */ + mfspr r20,DAR /* Get the new esid */ + rldicl r20,r20,36,28 /* Permits a full 36b of ESID */ + rldimi r1,r20,28,0 /* Insert the new esid value */ + ori r1,r1,144 /* Turn on valid and kp */ + std r1,0(r21) /* Put new entry back into the stab */ + sync /* Order the update */ + b 3f +2: + addi r22,r22,1 + addi r21,r21,16 + cmpldi r22,7 + ble 1b + + /* Stick for only searching the primary group for now. */ + /* At least for now, we use a very simple random castout scheme */ + /* Use the TB as a random number ; OR in 1 to avoid entry 0 */ + mftb r22 + andi. r22,r22,7 + ori r22,r22,1 + sldi r22,r22,4 + + /* r21 currently points to and ste one past the group of interest */ + /* make it point to the randomly selected entry */ + subi r21,r21,128 + ori r21,r21,r22 /* r21 is the entry to invalidate */ + + isync /* mark the entry invalid */ + ld r1,0(r21) + li r22,-129 + and r1,r1,r22 + std r1,0(r21) + sync + + ld r1,8(r21) + rldimi r1,r20,12,0 + std r1,8(r21) + eieio + + ld r1,0(r21) /* Get the esid part of the ste */ + mr r22,r1 + mfspr r20,DAR /* Get the new esid */ + rldicl r20,r20,36,32 /* Permits a full 32b of ESID */ + rldimi r1,r20,28,0 /* Insert the new esid value */ + ori r1,r1,144 /* Turn on valid and kp */ + std r1,0(r21) /* Put new entry back into the stab */ + + rldicl r22,r22,36,28 + rldicr r22,r22,28,35 + slbie r22 + sync + +3: + /* All done -- return from exception. */ + mfsprg r20,3 /* Load the PACA pointer */ + + ld r22,LPPACA+LPPACASRR0(r20); /* Get SRR0 from ItLpPaca */ + ld r21,LPPACA+LPPACASRR1(r20); /* Get SRR1 from ItLpPaca */ + mtspr SRR1,r21 + mtspr SRR0,r22 + + lwz r21,PACACCR(r20) /* Restore the clobbered regs */ + mtcr r21 + ld r1, PACAR1(r20) + ld r21,PACAR21(r20) + ld r22,PACAR22(r20) + mfspr r20,SPRG2 + rfid + _GLOBAL(do_stab_SI) mflr r21 /* Save LR in r21 */ /* r21 restored later from r1 */ @@ -670,17 +828,14 @@ SAVE_4GPRS(16, r21) SAVE_8GPRS(24, r21) /* - * Clear any reservation, and clear the RESULT field + * Clear the RESULT field */ - li r22,RESULT - stdcx. r22,r22,r21 /* to clear the reservation */ li r22,0 std r22,RESULT(r21) /* * Test if from user state; result will be tested later */ - andi. r23,r23,MSR_PR /* Set CR for later branch */ - /* SPRG3 -> PACA */ + andi. r23,r23,MSR_PR /* Set CR for later branch */ /* * Indicate that r1 contains the kernel stack and * get the Kernel TOC and CURRENT pointers from the Paca @@ -696,7 +851,6 @@ addi r24,r1,STACK_FRAME_OVERHEAD std r24,THREAD+PT_REGS(r22) 2: - /* * Since we store 'current' in the PACA now, we don't need to * set it here. When r2 was used as 'current' it had to be @@ -733,27 +887,37 @@ * At entry, r3 = this processor's number (in Linux terms, not hardware). */ _GLOBAL(pseries_secondary_smp_init) + + /* turn on 64-bit mode */ + bl .enable_64b_mode + isync + /* Set up a Paca value for this processor. */ LOADADDR(r24, xPaca) /* Get base vaddr of Paca array */ mulli r25,r3,PACA_SIZE /* Calculate vaddr of right Paca */ add r25,r25,r24 /* for this processor. */ - SET_REG_TO_CONST(r26,KERNELBASE) /* Calculate raddr of the Paca */ - sub r26,r25,r26 - mtspr SPRG3,r25 /* Save vaddr of Paca in SPRG3 */ mr r24,r3 /* __secondary_start needs cpu# */ 1: HMT_LOW - lbz r23,PACAPROCSTART(r26) /* Test if this processor should */ + lbz r23,PACAPROCSTART(r25) /* Test if this processor should */ /* start. */ + sync + LOADADDR(r3,current_set) + addi r3,r3,8 + sldi r28,r24,4 /* get current_set[cpu#] */ + ldx r1,r3,r28 + cmpi 0,r23,0 #ifdef CONFIG_SMP - bne .__secondary_start /* Loop until told to go. */ +#ifdef SECONDARY_PROCESSORS + bne .__secondary_start #endif - b 1b - +#endif + b 1b /* Loop until told to go */ + _GLOBAL(__start_initialization_iSeries) LOADADDR(r1,init_task_union) @@ -1071,68 +1235,57 @@ * On entry the following are set: * r24 = cpu# (in Linux terms) * r25 = Paca virtual address - * r26 = Paca physical address * SPRG3 = Paca virtual address */ _GLOBAL(__secondary_start) - /* turn on 64 bit mode */ - bl .enable_64b_mode - isync - - /* get our current offset. */ - SET_REG_TO_CONST(r27, KERNELBASE) HMT_MEDIUM /* Set thread priority to MEDIUM */ - /* get a virtual pointer to current */ - LOADADDR(r3,current_set) - sub r3,r3,r27 - addi r3,r3,8 - sldi r28,r24,4 /* get current_set[cpu#] */ - ldx r1,r3,r28 - /* set up the TOC (virtual address) */ LOADADDR(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 - std r2,PACATOC(r26) + std r2,PACATOC(r25) li r6,0 - std r6,PACAKSAVE(r26) + std r6,PACAKSAVE(r25) #ifndef CONFIG_PPC_ISERIES /* Initialize the page table pointer register. */ - LOADADDR(r6,_SDR1) - sub r6,r6,r27 + LOADADDR(r6,_SDR1) ld r6,0(r6) /* get the value of _SDR1 */ mtspr SDR1,r6 /* set the htab location */ #endif /* Initialize the segment table subsystem. */ - ld r4,PACASTABREAL(r26) /* get raddr of segment table */ - ori r3,r4,1 /* turn on valid bit */ - mtasr r3 /* set the stab location */ + ld r4,PACASTABVIRT(r25) /* get addr of segment table */ li r3,0 /* 0 -> include esid 0xC00000000 */ - slbia + std r3,0(r1) /* Zero the stack frame pointer */ bl .stab_initialize - /* get a virtual pointer to current */ - SET_REG_TO_CONST(r27, KERNELBASE) LOADADDR(r3,current_set) - sub r3,r3,r27 sldi r28,r24,4 /* get current_set[cpu#] */ ldx r6,r3,r28 + std r6,PACACURRENT(r25) addi r1,r6,TASK_UNION_SIZE subi r1,r1,STACK_FRAME_OVERHEAD - addi r3,r3,8 - ld r3,0(r3) + ld r3,PACASTABREAL(r25) /* get raddr of segment table */ + ori r4,r3,1 /* turn on valid bit */ + +#ifdef CONFIG_PPC_ISERIES + li r0,-1 /* hypervisor call */ + li r3,1 + sldi r3,r3,63 /* 0x8000000000000000 */ + ori r3,r3,4 /* 0x8000000000000004 */ + sc /* HvCall_setASR */ +#else + mtasr r4 /* set the stab location */ +#endif + slbia + li r7,0 - std r7,0(r3) mtlr r7 - mfspr r4,SPRG3 - std r6,PACACURRENT(r4) - /* enable MMU and jump to start_secondary */ LOADADDR(r3,.start_secondary) SET_REG_TO_CONST(r4, MSR_KERNEL) @@ -1356,6 +1509,10 @@ bolted_dir: .space 4096 +/* 4096 * 31 bytes of storage */ + .globl stab_array +stab_array: + .space 131072 /* * This space gets a copy of optional info passed to us by the bootstrap * Used to pass parameters into the kernel like root=/dev/sda1, etc. diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/htab.c linuxppc64_2_4/arch/ppc64/kernel/htab.c --- linux-2.4.8-ac9/arch/ppc64/kernel/htab.c Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/kernel/htab.c Tue Aug 21 14:49:26 2001 @@ -82,6 +82,22 @@ #define PTRUNRELOC(x) ((typeof(x))((unsigned long)(x) + offset)) #define RELOC(x) (*PTRRELOC(&(x))) +extern unsigned long htab_size( unsigned long ); + +static inline void +create_pte_mapping(unsigned long start, unsigned long end, + unsigned long mode, unsigned long mask) +{ + unsigned long addr, offset = reloc_offset(); + HTAB *_htab_data = PTRRELOC(&htab_data); + HPTE *htab = (HPTE *)__v2a(_htab_data->htab); + + for (addr=start; addr < end ;addr+=0x1000) { + unsigned long vsid = get_kernel_vsid(addr); + unsigned long va = (vsid << 28) | (addr & 0xfffffff); + make_pte(htab, va, (unsigned long)__v2a(addr), mode, mask); + } +} void htab_initialize(void) @@ -125,11 +141,18 @@ * (addr & KERNELBASE) == 0 (ie they are disjoint). * We also assume that the va is <= 64 bits. */ - create_pte_mapping(_stext, __start_naca, mode_ro, mask); - create_pte_mapping(__start_naca, __end_stab, mode_rw, mask); - create_pte_mapping(__end_stab, _etext, mode_ro, mask); - create_pte_mapping(_etext, RELOC(klimit), mode_rw, mask); - create_pte_mapping(__a2v(table), __a2v(table+htab_size_bytes), mode_rw, mask); +#if 0 + create_pte_mapping((unsigned long)_stext, (unsigned long)__start_naca, mode_ro, mask); + create_pte_mapping((unsigned long)__start_naca, (unsigned long)__end_stab, mode_rw, mask); + create_pte_mapping((unsigned long)__end_stab, (unsigned long)_etext, mode_ro, mask); + create_pte_mapping((unsigned long)_etext, RELOC(klimit), mode_rw, mask); + create_pte_mapping((unsigned long)__a2v(table), (unsigned long)__a2v(table+htab_size_bytes), mode_rw, mask); +#else + create_pte_mapping((unsigned long)KERNELBASE, + KERNELBASE+(_naca->physicalMemorySize), + mode_rw, mask); +#endif + } static inline unsigned long hpt_hash( unsigned long vpn ) @@ -150,6 +173,7 @@ { HPTE *hptep; unsigned long hash, i; + volatile unsigned long x = 1; hash = hpt_hash( va >> 12 ); @@ -162,9 +186,12 @@ hptep->dw0.dw0.avpn = va >> 23; hptep->dw0.dw0.bolted = 1; /* bolted */ hptep->dw0.dw0.v = 1; /* make valid */ - break; + return; } } + + /* We should _never_ get here and too early to call xmon. */ + for(;x;x|=1); } void invalidate_hpte( unsigned long slot ) @@ -318,6 +345,69 @@ return 0; } +static unsigned long get_hpte0( unsigned long slot ) +{ + unsigned long dword0; + + if ( _machine == _MACH_iSeries ) { + HPTE hpte; + HvCallHpt_get( &hpte, slot ); + dword0 = hpte.dw0.dword0; + } + else { + HPTE * hptep = htab_data.htab + slot; + dword0 = hptep->dw0.dword0; + } + + return dword0; +} + +long find_hpte( unsigned long vpn ) +{ + HPTE hpte; + long slot; + + if ( _machine == _MACH_iSeries ) { + slot = HvCallHpt_findValid( &hpte, vpn ); + if ( hpte.dw0.dw0.v ) { + if ( slot < 0 ) { + slot &= 0x7fffffffffffffff; + slot = -slot; + } + } + else + slot = -1; + } + else { + union { + unsigned long d; + Hpte_dword0 h; + } hpte_dw0; + unsigned long hash; + unsigned long i,j; + + hash = hpt_hash( vpn ); + for ( j=0; j<2; ++j ) { + slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP; + for ( i=0; i> 11 ) ) && + ( hpte_dw0.h.v ) && + ( hpte_dw0.h.h == j ) ) { + /* HPTE matches */ + if ( j ) + slot = -slot; + return slot; + } + ++slot; + } + hash = ~hash; + } + slot = -1; + } + return slot; +} + /* This function is called by btmalloc to bolt an entry in the hpt */ void build_valid_hpte( unsigned long vsid, unsigned long ea, unsigned long pa, pte_t * ptep, unsigned hpteflags, unsigned bolted ) @@ -474,23 +564,6 @@ 1 ) ); } -static unsigned long get_hpte0( unsigned long slot ) -{ - unsigned long dword0; - - if ( _machine == _MACH_iSeries ) { - HPTE hpte; - HvCallHpt_get( &hpte, slot ); - dword0 = hpte.dw0.dword0; - } - else { - HPTE * hptep = htab_data.htab + slot; - dword0 = hptep->dw0.dword0; - } - - return dword0; -} - static void updateHptePP( long slot, unsigned long newpp, unsigned long va ) { if ( _machine == _MACH_iSeries ) { @@ -552,6 +625,7 @@ long slot; struct mm_struct * mm; pte_t old_pte, new_pte, *ptep; + volatile unsigned long x = 1; /* Check for invalid addresses. */ if (!IS_VALID_EA(ea)) { @@ -561,6 +635,14 @@ regionid = REGION_ID(ea); switch ( regionid ) { case KERNEL_REGION_ID: + + /* As htab_initialize is now, we shouldn't ever get here since + * we're bolting the entire 0xC0... region. + */ + udbg_printf("Doh!!! hash_page saw a kernel address...\n"); + xmon(0); + for(;x;x|=1); + vsid = get_kernel_vsid( ea ); va = ( vsid << 28 ) | ( ea & 0x0fffffff ); vpn = va >> PAGE_SHIFT; @@ -568,7 +650,7 @@ pte_val(old_pte) = ((__pa(ea)&PAGE_MASK)<<(PTE_SHIFT-PAGE_SHIFT)) | _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED | _PAGE_RW | _PAGE_COHERENT | - _PAGE_DIRTY | _PAGE_HASHPTE; + _PAGE_DIRTY | _PAGE_HPTENOIX; spin_lock( &hash_table_lock ); break; case VMALLOC_REGION_ID: @@ -669,6 +751,24 @@ access |= _PAGE_PRESENT; if ( 0 == ( access & ~(pte_val(old_pte)) ) ) { + /* + * Check if pte might have an hpte, but we have + * no slot information + */ + if ( pte_val(old_pte) & _PAGE_HPTENOIX ) { + unsigned long slot; + pte_val(old_pte) &= ~_PAGE_HPTEFLAGS; + slot = find_hpte( vpn ); + if ( slot != -1 ) { + if ( slot < 0 ) { + pte_val(old_pte) |= _PAGE_SECONDARY; + slot = -slot; + } + pte_val(old_pte) |= ((slot << 12) & _PAGE_GROUP_IX) | _PAGE_HASHPTE; + + } + } + /* User has appropriate access rights. */ new_pte = old_pte; /* If the attempted access was a store */ @@ -848,6 +948,25 @@ /* HPTE matches */ invalidate_hpte( slot ); } + else { + unsigned k; + /* Temporarily lets check for the hpte in all possible slots */ + for ( secondary = 0; secondary < 2; ++secondary ) { + hash = hpt_hash( vpn ); + if ( secondary ) + hash = ~hash; + slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP; + for ( k=0; k<8; ++k ) { + hpte_dw0.d = get_hpte0( slot+k ); + if ( ( hpte_dw0.h.avpn == (vpn >> 11) ) && + ( hpte_dw0.h.v ) && + ( hpte_dw0.h.h == secondary ) ) { + while (1) ; + } + } + } + + } spin_unlock_irqrestore( &hash_table_lock, flags ); } @@ -1042,20 +1161,5 @@ pteg_count >>= 3; } return (pteg_count << 7); /* pteg_count*128B/PTEG */ -} - -static inline void -create_pte_mapping(unsigned long start, unsigned long end, - unsigned long mode, unsigned long mask) -{ - unsigned long addr, offset = reloc_offset(); - HTAB *_htab_data = PTRRELOC(&htab_data); - HPTE *htab = (HPTE *)__v2a(_htab_data->htab); - - for (addr=start; addr < end ;addr+=0x1000) { - unsigned long vsid = get_kernel_vsid(addr); - unsigned long va = (vsid << 28) | (addr & 0xfffffff); - make_pte(htab, va, __v2a(addr), mode, mask); - } } diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/iSeries_IoMmTable.c linuxppc64_2_4/arch/ppc64/kernel/iSeries_IoMmTable.c --- linux-2.4.8-ac9/arch/ppc64/kernel/iSeries_IoMmTable.c Wed Dec 31 18:00:00 1969 +++ linuxppc64_2_4/arch/ppc64/kernel/iSeries_IoMmTable.c Fri Aug 24 06:41:08 2001 @@ -0,0 +1,187 @@ +/************************************************************************/ +/* This module supports the iSeries I/O Address translation mapping */ +/* Copyright (C) 20yy */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the: */ +/* Free Software Foundation, Inc., */ +/* 59 Temple Place, Suite 330, */ +/* Boston, MA 02111-1307 USA */ +/************************************************************************/ +/* Change Activity: */ +/* Created, December 14, 2000 */ +/* Added Bar table for IoMm performance. */ +/* End Change Activity */ +/************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +#include "iSeries_IoMmTable.h" +#include "pci.h" + +void iSeries_allocateDeviceBars(struct pci_dev* PciDevPtr); +/*******************************************************************/ +/* Table defines */ +/* Entry size is 4 MB * 1024 Entries = 4GB. */ +/*******************************************************************/ +#define iSeries_IoMmTable_Entry_Size 0x00400000 +#define iSeries_IoMmTable_Size 1024 +#define iSeries_Base_Io_Memory 0xFFFFFFFF + +/*******************************************************************/ +/* Static and Global variables */ +/*******************************************************************/ +struct pci_dev* iSeries_IoMmTable[iSeries_IoMmTable_Size]; +u8 iSeries_IoBarTable[iSeries_IoMmTable_Size]; +static int iSeries_CurrentIndex; +static char* iSeriesPciIoText = "iSeries PCI I/O"; +static spinlock_t iSeriesIoMmTableLock = SPIN_LOCK_UNLOCKED; +/*******************************************************************/ +/* iSeries_IoMmTable_Initialize */ +/*******************************************************************/ +/* - Initalizes the Address Translation Table and get it ready for */ +/* use. Must be called before any client calls any of the other */ +/* methods. */ +/*******************************************************************/ +void iSeries_IoMmTable_Initialize(void) { + int Index; + spin_lock(&iSeriesIoMmTableLock); + for(Index=0;Indexresource[BarNumber]; + iSeries_IoMmTable_AllocateEntry(PciDev, BarNumber); + } +} + +/*******************************************************************/ +/* iSeries_IoMmTable_AllocateEntry */ +/*******************************************************************/ +/* Adds pci_dev entry in address translation table */ +/*******************************************************************/ +/* - Allocates the number of entries required in table base on BAR */ +/* size. */ +/* - This version, allocates top down, starting at 4GB. */ +/* - The size is round up to be a multiple of entry size. */ +/* - CurrentIndex is decremented to keep track of the last entry. */ +/* - Builds the resource entry for allocated BARs. */ +/*******************************************************************/ +void iSeries_IoMmTable_AllocateEntry(struct pci_dev* PciDev, int BarNumber) { + struct resource* BarResource = &PciDev->resource[BarNumber]; + int BarSize = BarResource->end - BarResource->start; + unsigned long BarStartAddr; + unsigned long BarEndAddr; + /***************************************************************/ + /* No space to allocate, skip Allocation. */ + /***************************************************************/ + if(BarSize == 0) return; /* Quick stage exit */ + + /***************************************************************/ + /* Allocate the table entries needed. */ + /***************************************************************/ + spin_lock(&iSeriesIoMmTableLock); + while(BarSize > 0) { + iSeries_IoMmTable[iSeries_CurrentIndex] = PciDev; + iSeries_IoBarTable[iSeries_CurrentIndex] = BarNumber; + BarSize -= iSeries_IoMmTable_Entry_Size; + --iSeries_CurrentIndex; /* Next Free entry */ + } + spin_unlock(&iSeriesIoMmTableLock); + BarStartAddr = iSeries_IoMmTable_Entry_Size*(iSeries_CurrentIndex+1); + BarEndAddr = BarStartAddr + (BarResource->end - BarResource->start); + /***************************************************************/ + /* Build Resource info */ + /***************************************************************/ + BarResource->name = iSeriesPciIoText; + BarResource->start = (long)BarStartAddr; + BarResource->end = (long)BarEndAddr; + + PPCDBG(PPCDBG_BUSWALK,"BarAloc %04X-%016LX\n",iSeries_CurrentIndex+1,BarStartAddr); +} +/*******************************************************************/ +/* Translates an I/O Memory address to pci_dev* */ +/*******************************************************************/ +struct pci_dev* iSeries_xlateIoMmAddress(unsigned long* IoAddress) { + int PciDevIndex = (unsigned long)IoAddress/iSeries_IoMmTable_Entry_Size; + struct pci_dev* PciDev = iSeries_IoMmTable[PciDevIndex]; + if(PciDev == 0) { + printk("PCI: Invalid I/O Address: 0x%016LX\n",IoAddress); + PCIFR("Invalid MMIO Address 0x%016LX",(unsigned long)IoAddress); + } + return PciDev; +} +/************************************************************************/ +/* Returns the Bar number of Address */ +/************************************************************************/ +int iSeries_IoMmTable_Bar(unsigned long* IoAddress) { + int BarIndex = (unsigned long)IoAddress/iSeries_IoMmTable_Entry_Size; + int BarNumber = iSeries_IoBarTable[BarIndex]; + return BarNumber; +} +/************************************************************************/ +/* Return the Bar Base Address or 0. */ +/************************************************************************/ +unsigned long* iSeries_IoMmTable_BarBase(unsigned long* IoAddress) { + unsigned long BaseAddr = 0; + struct pci_dev* PciDev = iSeries_xlateIoMmAddress(IoAddress); + if(PciDev != NULL) { + int BarNumber = iSeries_IoMmTable_Bar(IoAddress); + if(BarNumber != -1) { + BaseAddr = PciDev->resource[BarNumber].start; + } + } + return (unsigned long*)BaseAddr; +} +/************************************************************************/ +/* Return the Bar offset within the Bar Space */ +/* Note: Assumes that address is valid. */ +/************************************************************************/ +unsigned long iSeries_IoMmTable_BarOffset(unsigned long* IoAddress) { + return (unsigned long)IoAddress-(unsigned long)iSeries_IoMmTable_BarBase(IoAddress); +} +/************************************************************************/ +/* Return 0 if Address is valid I/O Address */ +/************************************************************************/ +int iSeries_Is_IoMmAddress(unsigned long* IoAddress) { + if( iSeries_xlateIoMmAddress(IoAddress) == NULL) return 1; + else return 0; +} + + diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/iSeries_IoMmTable.h linuxppc64_2_4/arch/ppc64/kernel/iSeries_IoMmTable.h --- linux-2.4.8-ac9/arch/ppc64/kernel/iSeries_IoMmTable.h Wed Dec 31 18:00:00 1969 +++ linuxppc64_2_4/arch/ppc64/kernel/iSeries_IoMmTable.h Fri Aug 24 06:41:08 2001 @@ -0,0 +1,99 @@ +#ifndef _ISERIES_IOMMTABLE_H +#define _ISERIES_IOMMTABLE_H +/************************************************************************/ +/* File iSeries_IoMmTable.h created by Allan Trautman on Dec 12 2001. */ +/************************************************************************/ +/* Interfaces for the write/read Io address translation table. */ +/* Copyright (C) 20yy Allan H Trautman, IBM Corporation */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the: */ +/* Free Software Foundation, Inc., */ +/* 59 Temple Place, Suite 330, */ +/* Boston, MA 02111-1307 USA */ +/************************************************************************/ +/* Change Activity: */ +/* Created December 12, 2000 */ +/* End Change Activity */ +/************************************************************************/ + +/************************************************************************/ +/* iSeries_IoMmTable_Initialize */ +/************************************************************************/ +/* - Initalizes the Address Translation Table and get it ready for use. */ +/* Must be called before any client calls any of the other methods. */ +/* */ +/* Parameters: None. */ +/* */ +/* Return: None. */ +/************************************************************************/ +extern void iSeries_IoMmTable_Initialize(void); + +/************************************************************************/ +/* iSeries_allocateDeviceBars */ +/************************************************************************/ +/* - Allocates ALL pci_dev BAR's and updates the resources with the BAR */ +/* value. BARS with zero length will not have the resources. The */ +/* HvCallPci_getBarParms is used to get the size of the BAR space. */ +/* It calls as400_IoMmTable_AllocateEntry to allocate each entry. */ +/* */ +/* Parameters: */ +/* pci_dev = Pointer to pci_dev structure that will be mapped to pseudo */ +/* I/O Address. */ +/* */ +/* Return: */ +/* The pci_dev I/O resources updated with pseudo I/O Addresses. */ +/************************************************************************/ +extern void iSeries_allocateDeviceBars(struct pci_dev* ); + +/************************************************************************/ +/* iSeries_IoMmTable_AllocateEntry */ +/************************************************************************/ +/* - Allocates(adds) the pci_dev entry in the Address Translation Table */ +/* and updates the Resources for the device. */ +/* */ +/* Parameters: */ +/* pci_dev = Pointer to pci_dev structure that will be mapped to pseudo */ +/* I/O Address. */ +/* */ +/* BarNumber = Which Bar to be allocated. */ +/* */ +/* Return: */ +/* The pseudo I/O Address in the resources that will map to the */ +/* pci_dev on iSeries_xlateIoMmAddress call. */ +/************************************************************************/ +extern void iSeries_IoMmTable_AllocateEntry(struct pci_dev* , int BarNumber); + +/************************************************************************/ +/* iSeries_xlateIoMmAddress */ +/************************************************************************/ +/* - Translates an I/O Memory address to pci_dev that has been allocated*/ +/* the psuedo I/O Address. */ +/* */ +/* Parameters: */ +/* IoAddress = I/O Memory Address. */ +/* */ +/* Return: */ +/* A pci_dev pointer to the device mapped to the I/O address. */ +/************************************************************************/ +extern struct pci_dev* iSeries_xlateIoMmAddress(unsigned long* IoAddress); + +/************************************************************************/ +/* Helper Methods */ +/************************************************************************/ +extern int iSeries_IoMmTable_Bar(unsigned long *IoAddress); +extern unsigned long* iSeries_IoMmTable_BarBase(unsigned long* IoAddress); +extern unsigned long iSeries_IoMmTable_BarOffset(unsigned long* IoAddress); +extern int iSeries_Is_IoMmAddress(unsigned long* IoAddress); + +#endif /* _ISERIES_IOMMTABLE_H */ diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/iSeries_VpdInfo.c linuxppc64_2_4/arch/ppc64/kernel/iSeries_VpdInfo.c --- linux-2.4.8-ac9/arch/ppc64/kernel/iSeries_VpdInfo.c Wed Dec 31 18:00:00 1969 +++ linuxppc64_2_4/arch/ppc64/kernel/iSeries_VpdInfo.c Fri Aug 24 06:41:08 2001 @@ -0,0 +1,360 @@ +/************************************************************************/ +/* File iSeries_vpdInfo.c created by Allan Trautman on Fri Feb 2 2001. */ +/************************************************************************/ +/* This code gets the card location of the hardware */ +/* Copyright (C) 20yy */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the: */ +/* Free Software Foundation, Inc., */ +/* 59 Temple Place, Suite 330, */ +/* Boston, MA 02111-1307 USA */ +/************************************************************************/ +/* Change Activity: */ +/* Created, Feb 2, 2001 */ +/* Ported to ppc64, August 20, 2001 */ +/* End Change Activity */ +/************************************************************************/ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "pci.h" + +/************************************************/ +/* Size of Bus VPD data */ +/************************************************/ +#define BUS_VPDSIZE 1024 +/************************************************/ +/* Bus Vpd Tags */ +/************************************************/ +#define VpdEndOfDataTag 0x78 +#define VpdEndOfAreaTag 0x79 +#define VpdIdStringTag 0x82 +#define VpdVendorAreaTag 0x84 +/************************************************/ +/* Mfg Area Tags */ +/************************************************/ +#define VpdAsmPartNumber 0x504E // "PN" +#define VpdFruFlag 0x4647 // "FG" +#define VpdFruLocation 0x464C // "FL" +#define VpdFruFrameId 0x4649 // "FI" +#define VpdFruPartNumber 0x464E // "FN" +#define VpdFruPowerData 0x5052 // "PR" +#define VpdFruSerial 0x534E // "SN" +#define VpdFruType 0x4343 // "CC" +#define VpdFruCcinExt 0x4345 // "CE" +#define VpdFruRevision 0x5256 // "RV" +#define VpdSlotMapFormat 0x4D46 // "MF" +#define VpdSlotMap 0x534D // "SM" + +/************************************************/ +/* Structures of the areas */ +/************************************************/ +struct BusVpdAreaStruct { + u8 Tag; + u8 LowLength; + u8 HighLength; +}; +typedef struct BusVpdAreaStruct BusVpdArea; +#define BUS_ENTRY_SIZE 3 + +struct MfgVpdAreaStruct { + u16 Tag; + u8 TagLength; +}; +typedef struct MfgVpdAreaStruct MfgVpdArea; +#define MFG_ENTRY_SIZE 3 + +struct SlotMapFormatStruct { + u16 Tag; + u8 TagLength; + u16 Format; +}; + +struct FrameIdMapStruct{ + u16 Tag; + u8 TagLength; + u8 FrameId; +}; +typedef struct FrameIdMapStruct FrameIdMap; + +struct SlotMapStruct { + u8 AgentId; + u8 SecondaryAgentId; + u8 PhbId; + char CardLocation[3]; + char Parms[8]; + char Reserved[2]; +}; +typedef struct SlotMapStruct SlotMap; +#define SLOT_ENTRY_SIZE 16 + +/****************************************************************/ +/* Prototypes */ +/****************************************************************/ +static void iSeries_Parse_Vpd(BusVpdArea*, int, LocationData*); +static void iSeries_Parse_MfgArea(MfgVpdArea*,int, LocationData*); +static void iSeries_Parse_SlotArea(SlotMap*, int, LocationData*); +static void iSeries_Parse_PhbId(BusVpdArea*, int, LocationData*); + +/**************************************************************** + * iSeries_loc-code(struct pci_dev* PciDev) * + * * + * Gets the frame and card location of the pci_dev device. The * + * return is a kmalloc string. The user must free this string * + * when they are done. This is specifically for the device tree* + * * + * Returns: * + * "Frame 1, Card C10" * + ****************************************************************/ +char* iSeries_Location_Code(struct pci_dev* PciDev) { + char TempBuffer[128]; + LocationData* LocationPtr = iSeries_GetLocationData(PciDev); + int LineLen = sprintf(TempBuffer," Frame%3d, Card %4s ", + LocationPtr->FrameId,LocationPtr->CardLocation); + char* RtnString = kmalloc(LineLen+7,GFP_KERNEL); + strcpy(RtnString,TempBuffer); + kfree(LocationPtr); + return RtnString; +} +/****************************************************************/ +/* */ +/* */ +/* */ +/****************************************************************/ +LocationData* iSeries_GetLocationData(struct pci_dev* PciDev) { + LocationData* LocationPtr = 0; + BusVpdArea* BusVpdPtr = 0; + int BusVpdLen = 0; + BusVpdPtr = (BusVpdArea*)kmalloc(BUS_VPDSIZE, GFP_KERNEL); + BusVpdLen = HvCallPci_getBusVpd(PciDev->bus->number,REALADDR(BusVpdPtr),BUS_VPDSIZE); + /* printk("PCI: VpdBuffer 0x%08X \n",(int)BusVpdPtr); */ + /***************************************************************/ + /* Need to set Agent Id, Bus in location info before the call */ + /***************************************************************/ + LocationPtr = (LocationData*)kmalloc(LOCATION_DATA_SIZE, GFP_KERNEL); + LocationPtr->Bus = PciDev->bus->number; + LocationPtr->Board = 0; + LocationPtr->FrameId = 0; + iSeries_Parse_PhbId(BusVpdPtr,BusVpdLen,LocationPtr); + LocationPtr->Card = PCI_SLOT(PciDev->devfn); + strcpy(LocationPtr->CardLocation,"Cxx"); + LocationPtr->AgentId = ISERIES_DECODE_DEVICE(PciDev->devfn); + LocationPtr->SecondaryAgentId = 0x10; + /* And for Reference only. */ + LocationPtr->LinuxBus = PciDev->bus->number; + LocationPtr->LinuxDevFn = PciDev->devfn; + /***************************************************************/ + /* Any data to process? */ + /***************************************************************/ + if(BusVpdLen > 0) { + iSeries_Parse_Vpd(BusVpdPtr, BUS_VPDSIZE, LocationPtr); + } + else { + PCIFR("No VPD Data...."); + } + kfree(BusVpdPtr); + + return LocationPtr; +} +/****************************************************************/ +/* */ +/****************************************************************/ +void iSeries_Parse_Vpd(BusVpdArea* VpdData,int VpdLen, LocationData* LocationPtr) { + MfgVpdArea* MfgVpdPtr = 0; + int BusTagLen = 0; + BusVpdArea* BusVpdPtr = VpdData; + int BusVpdLen = VpdLen; + /*************************************************************/ + /* Make sure this is what I think it is */ + /*************************************************************/ + if(BusVpdPtr->Tag != VpdIdStringTag) { /*0x82 */ + PCIFR("Not 0x82 start of VPD."); + return; + } + BusTagLen = (BusVpdPtr->HighLength*256)+BusVpdPtr->LowLength; + BusTagLen += BUS_ENTRY_SIZE; + BusVpdPtr = (BusVpdArea*)((u32)BusVpdPtr+BusTagLen); + BusVpdLen -= BusTagLen; + /*************************************************************/ + /* Parse the Data */ + /*************************************************************/ + while(BusVpdLen > 0 ) { + BusTagLen = (BusVpdPtr->HighLength*256)+BusVpdPtr->LowLength; + /*********************************************************/ + /* End of data Found */ + /*********************************************************/ + if(BusVpdPtr->Tag == VpdEndOfAreaTag) { + BusVpdLen = 0; /* Done, Make sure */ + } + /*********************************************************/ + /* Was Mfg Data Found */ + /*********************************************************/ + else if(BusVpdPtr->Tag == VpdVendorAreaTag) { + MfgVpdPtr = (MfgVpdArea*)((u32)BusVpdPtr+BUS_ENTRY_SIZE); + iSeries_Parse_MfgArea(MfgVpdPtr,BusTagLen,LocationPtr); + } + /********************************************************/ + /* On to the next tag. */ + /********************************************************/ + if(BusVpdLen > 0) { + BusTagLen += BUS_ENTRY_SIZE; + BusVpdPtr = (BusVpdArea*)((u32)BusVpdPtr+BusTagLen); + BusVpdLen -= BusTagLen; + } + } +} + +/*****************************************************************/ +/* Parse the Mfg Area */ +/*****************************************************************/ +void iSeries_Parse_MfgArea(MfgVpdArea* VpdDataPtr,int VpdLen, LocationData* LocationPtr) { + SlotMap* SlotMapPtr = 0; + u16 SlotMapFmt = 0; + int MfgTagLen = 0; + MfgVpdArea* MfgVpdPtr = VpdDataPtr; + int MfgVpdLen = VpdLen; + + /*************************************************************/ + /* Parse Mfg Data */ + /*************************************************************/ + while(MfgVpdLen > 0) { + MfgTagLen = MfgVpdPtr->TagLength; + if (MfgVpdPtr->Tag == VpdFruFlag) {} /* FG */ + else if(MfgVpdPtr->Tag == VpdFruSerial) {} /* SN */ + else if(MfgVpdPtr->Tag == VpdAsmPartNumber){} /* PN */ + /*********************************************************/ + /* Frame ID */ + /*********************************************************/ + if(MfgVpdPtr->Tag == VpdFruFrameId) { /* FI */ + LocationPtr->FrameId = ((FrameIdMap*)MfgVpdPtr)->FrameId; + } + /*********************************************************/ + /* Slot Map Format */ + /*********************************************************/ + else if(MfgVpdPtr->Tag == VpdSlotMapFormat){ /* MF */ + SlotMapFmt = ((struct SlotMapFormatStruct*)MfgVpdPtr)->Format; + } + /*********************************************************/ + /* Slot Labels */ + /*********************************************************/ + else if(MfgVpdPtr->Tag == VpdSlotMap){ /* SM */ + if(SlotMapFmt == 0x1004) SlotMapPtr = (SlotMap*)((u32)MfgVpdPtr+MFG_ENTRY_SIZE+1); + else SlotMapPtr = (SlotMap*)((u32)MfgVpdPtr+MFG_ENTRY_SIZE); + iSeries_Parse_SlotArea(SlotMapPtr,MfgTagLen, LocationPtr); + } + /*********************************************************/ + /* Point to the next Mfg Area */ + /* Use defined size, sizeof give wrong answer */ + /*********************************************************/ + MfgTagLen += MFG_ENTRY_SIZE; + MfgVpdPtr = (MfgVpdArea*)( (u32)MfgVpdPtr + MfgTagLen); + MfgVpdLen -= MfgTagLen; + } +} +/*****************************************************************/ +/* Look for "BUS" Tag to set the PhbId. */ +/*****************************************************************/ +void iSeries_Parse_PhbId(BusVpdArea* VpdData,int VpdLen,LocationData* LocationPtr) { + int PhbId = 0xff; /* Not found flag */ + char* PhbPtr = (char*)VpdData+3; /* Skip over 82 tag */ + int DataLen = VpdLen; + while(DataLen > 0) { + if(*PhbPtr == 'B' && *(PhbPtr+1) == 'U' && *(PhbPtr+2) == 'S') { + if(*(PhbPtr+3) == ' ') PhbPtr += 4;/* Skip white spac*/ + else PhbPtr += 3; + if (*PhbPtr == '0') PhbId = 0; /* Don't convert, */ + else if(*PhbPtr == '1') PhbId = 1; /* Sanity check */ + else if(*PhbPtr == '2') PhbId = 2; /* values */ + DataLen = 0; /* Exit loop. */ + } + ++PhbPtr; + --DataLen; + } + LocationPtr->PhbId = PhbId; +} +/*****************************************************************/ +/* Parse the Slot Area */ +/*****************************************************************/ +void iSeries_Parse_SlotArea(SlotMap* MapPtr,int MapLen, LocationData* LocationPtr) { + int SlotMapLen = MapLen; + SlotMap* SlotMapPtr = MapPtr; + /*************************************************************/ + /* Parse Slot label until we find the one requrested */ + /*************************************************************/ + while(SlotMapLen > 0) { + if(SlotMapPtr->AgentId == LocationPtr->AgentId && + SlotMapPtr->SecondaryAgentId == LocationPtr->SecondaryAgentId) { + /*****************************************************/ + /* If Phb wasn't found, grab the first one found. */ + /*****************************************************/ + if(LocationPtr->PhbId == 0xff) LocationPtr->PhbId = SlotMapPtr->PhbId; + if( SlotMapPtr->PhbId == LocationPtr->PhbId ) { + /*****************************************************/ + /* Found what we were looking for, extract the data. */ + /*****************************************************/ + memcpy(&LocationPtr->CardLocation,&SlotMapPtr->CardLocation,3); + LocationPtr->CardLocation[3] = 0; /* Null terminate*/ + SlotMapLen = 0; /* We are done */ + } + } + /*********************************************************/ + /* Point to the next Slot */ + /* Use defined size, sizeof may give wrong answer */ + /*********************************************************/ + SlotMapLen -= SLOT_ENTRY_SIZE; + SlotMapPtr = (SlotMap*)((u32)SlotMapPtr+SLOT_ENTRY_SIZE); + } +} +/************************************************************************/ +/* Formats the device information. */ +/* - Pass in pci_dev* pointer to the device. */ +/* - Pass in buffer to place the data. Danger here is the buffer must */ +/* be as big as the client says it is. Should be at least 128 bytes.*/ +/* Return will the length of the string data put in the buffer. */ +/* Format: */ +/* PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet */ +/* controller */ +/************************************************************************/ +int iSeries_Device_Information(struct pci_dev* PciDev,char* Buffer, int BufferSize) { + LocationData* LocationPtr; /* VPD Information */ + char* BufPtr = Buffer; + int LineLen = 0; + if(BufferSize >= 128) { + LineLen = sprintf(BufPtr+LineLen,"PCI: Bus%3d, Device%3d, Vendor %04X ", + PciDev->bus->number, PCI_SLOT(PciDev->devfn),PciDev->vendor); + + LocationPtr = iSeries_GetLocationData(PciDev); + LineLen += sprintf(BufPtr+LineLen," Frame%3d, Card %4s ", + LocationPtr->FrameId,LocationPtr->CardLocation); + kfree(LocationPtr); + + if(pci_class_name(PciDev->class >> 8) == 0) { + LineLen += sprintf(BufPtr+LineLen,"0x%04X ",(int)(PciDev->class >> 8)); + } + else { + LineLen += sprintf(BufPtr+LineLen,"%s",pci_class_name(PciDev->class >> 8) ); + } + } + return LineLen; +} diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/iSeries_setup.c linuxppc64_2_4/arch/ppc64/kernel/iSeries_setup.c --- linux-2.4.8-ac9/arch/ppc64/kernel/iSeries_setup.c Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/kernel/iSeries_setup.c Fri Aug 24 09:49:43 2001 @@ -54,7 +54,7 @@ extern void abort(void); static void build_iSeries_Memory_Map( void ); static void setup_iSeries_cache_sizes( void ); -static void iSeries_bolt_kernel( unsigned long pages_to_bolt ); +static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr); extern void ppcdbg_initialize(void); /* Global Variables */ @@ -92,7 +92,7 @@ */ if ( naca->xRamDisk ) { - initrd_start = __va(naca->xRamDisk); + initrd_start = (unsigned long)__va(naca->xRamDisk); initrd_end = initrd_start + naca->xRamDiskSize * PAGE_SIZE; initrd_below_start_ok = 1; // ramdisk in kernel space ROOT_DEV = MKDEV( RAMDISK_MAJOR, 0 ); @@ -243,7 +243,7 @@ loadAreaFirstChunk = (u32)addr_to_chunk(itLpNaca.xLoadAreaAddr); loadAreaSize = itLpNaca.xLoadAreaChunks; - + /* Only add the pages already mapped here. * Otherwise we might add the hpt pages * The rest of the pages of the load area @@ -256,7 +256,7 @@ loadAreaLastChunk = loadAreaFirstChunk + loadAreaSize - 1; printk( "Mapping load area - physical addr = 0000000000000000\n" - " absolute addr = %016x\n", + " absolute addr = %016lx\n", chunk_to_addr(loadAreaFirstChunk) ); printk( "Load area size %dK\n", loadAreaSize*256 ); @@ -275,7 +275,7 @@ hptSizeChunks = hptSizePages >> (msChunks.chunk_shift-PAGE_SHIFT); hptLastChunk = hptFirstChunk + hptSizeChunks - 1; - printk( "HPT absolute addr = %016x, size = %dK\n", + printk( "HPT absolute addr = %016lx, size = %dK\n", chunk_to_addr(hptFirstChunk), hptSizeChunks*256 ); /* Fill in the htab_data structure */ @@ -289,7 +289,7 @@ htab_data.htab = NULL; /* Update the page table to bolt the kernel */ - iSeries_bolt_kernel( __pa(((unsigned long)_end + PAGE_SIZE) & ~PAGE_SIZE) >> PAGE_SHIFT ); + iSeries_bolt_kernel( 0, __pa(PAGE_ALIGN((unsigned long)_end)) ); /* Determine if absolute memory has any * holes so that we can interpret the @@ -357,6 +357,13 @@ * nextPhysChunk */ naca->physicalMemorySize = chunk_to_addr(nextPhysChunk); + + iSeries_bolt_kernel( __pa(PAGE_ALIGN((unsigned long)_end)), naca->physicalMemorySize ); + + lmb_init(); + lmb_add( 0, naca->physicalMemorySize ); + lmb_reserve( 0, __pa(klimit)); + } /* @@ -390,22 +397,27 @@ } /* - * Bolt the kernel (text and data) into the HPT + * Bolt the kernel addr space into the HPT */ -static void __init iSeries_bolt_kernel( unsigned long pages_to_bolt ) +static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr) { - unsigned long vsid, va, vpn, slot, i; + unsigned long pa; + unsigned long mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX; HPTE hpte; - for ( i=0; i> PAGE_SHIFT; - slot = HvCallHpt_findValid( &hpte, vpn ); + for (pa=saddr; pa < eaddr ;pa+=PAGE_SIZE) { + unsigned long ea = __va(pa); + unsigned long vsid = get_kernel_vsid( ea ); + unsigned long va = ( vsid << 28 ) | ( pa & 0xfffffff ); + unsigned long vpn = va >> PAGE_SHIFT; + unsigned long slot = HvCallHpt_findValid( &hpte, vpn ); if ( hpte.dw0.dw0.v ) { - /* Mark the page as bolted */ + /* HPTE exists, so just bolt it */ HvCallHpt_setSwBits( slot, 0x10, 0 ); + } else { + /* No HPTE exists, so create a new bolted one */ + build_valid_hpte(vsid, ea, pa, NULL, mode_rw, 1); } } } @@ -502,6 +514,77 @@ return (len); } +#ifdef CONFIG_SMP +void iSeries_spin_lock(spinlock_t *lock) +{ + int i; + for (;;) { + for (i=1024; i>0; --i) { + HMT_low(); + if ( lock->lock == 0 ) { + HMT_medium(); + if ( __spin_trylock(lock) ) + return; + } + } + HMT_medium(); + HvCallCfg_getLps(); + } +} + +void iSeries_read_lock(__rwlock_t *rw) +{ + int i; + for (;;) { + for (i=1024; i>0; --i) { + HMT_low(); + if ( rw->lock >= 0 ) { + HMT_medium(); + if ( __read_trylock(rw) ) + return; + } + } + HMT_medium(); + HvCallCfg_getLps(); + } +} + +void iSeries_write_lock(__rwlock_t *rw) +{ + int i; + for (;;) { + for (i=1024; i>0; --i) { + HMT_low(); + if ( rw->lock == 0 ) { + HMT_medium(); + if ( __write_trylock(rw) ) + return; + } + } + HMT_medium(); + HvCallCfg_getLps(); + } +} + +void iSeries_brlock_spin( spinlock_t *lock ) +{ + int i; + for(;;) { + for (i=1024; i>0; --i) { + HMT_low(); + if (lock->lock == 0) { + HMT_medium(); + return; + } + + } + HMT_medium(); + HvCallCfg_getLps(); + } +} + +#endif /* CONFIG_SMP */ + int iSeries_get_cpuinfo(char *buffer) { int len = 0; @@ -605,7 +688,7 @@ * Set the RTC in the virtual service processor * This requires flowing LpEvents to the primary partition */ -int __init +int iSeries_set_rtc_time(unsigned long time) { mf_setRtcTime(time); @@ -616,7 +699,7 @@ * Get the RTC from the virtual service processor * This requires flowing LpEvents to the primary partition */ -unsigned long __init +unsigned long iSeries_get_rtc_time(void) { unsigned long time; diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/idle.c linuxppc64_2_4/arch/ppc64/kernel/idle.c --- linux-2.4.8-ac9/arch/ppc64/kernel/idle.c Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/kernel/idle.c Wed Aug 15 08:37:55 2001 @@ -31,41 +31,91 @@ #include #include -static void power_save(void) +#include +#include +#include + +unsigned long maxYieldTime = 0; +unsigned long minYieldTime = 0xffffffffffffffffUL; + +static void yield_shared_processor(void) { - /* Implement me */ ; + struct Paca *paca; + unsigned long tb; + unsigned long yieldTime; + + /* Turn off the run light */ + unsigned long CTRL; + CTRL = mfspr(CTRLF); + CTRL &= ~RUNLATCH; + mtspr(CTRLT, CTRL); + + HMT_low(); + + paca = (struct Paca *)mfspr(SPRG3); + HvCall_setEnabledInterrupts( HvCall_MaskIPI | + HvCall_MaskLpEvent | + HvCall_MaskLpProd | + HvCall_MaskTimeout ); + + __cli(); + __sti(); + tb = get_tb(); + /* Compute future tb value when yield should expire */ + HvCall_yieldProcessor( HvCall_YieldTimed, tb+tb_ticks_per_jiffy ); + + yieldTime = get_tb() - tb; + if ( yieldTime > maxYieldTime ) + maxYieldTime = yieldTime; + + if ( yieldTime < minYieldTime ) + minYieldTime = yieldTime; + + /* + * disable/enable will force any pending interrupts + * to be seen. + */ + __cli(); + /* + * The decrementer stops during the yield. Just force + * a fake decrementer now and the timer interrupt code + * will straighten it all out. We have to do this + * while disabled so we don't do it between where it is + * checked and where it is reset. + */ + + paca->xLpPaca.xIntDword.xFields.xDecrInt = 1; + __sti(); } int idled(void) { - int do_power_save = 0; + struct Paca *paca; + long oldval; /* endless loop with no priority at all */ current->nice = 20; current->counter = -100; init_idle(); - for (;;) { -#ifdef CONFIG_SMP - int oldval; + paca = (struct Paca *)mfspr(SPRG3); - if (!do_power_save) { - /* - * Deal with another CPU just having chosen a thread to - * run here: - */ + for (;;) { + + if ( paca->xLpPaca.xSharedProc ) { + if ( !current->need_resched ) + yield_shared_processor(); + } + else { + /* Avoid an IPI by setting need_resched */ oldval = xchg(¤t->need_resched, -1); - if (!oldval) { while(current->need_resched == -1) - ; /* Do Nothing */ + HMT_low(); } } -#endif - if (do_power_save && !current->need_resched) - power_save(); - if (current->need_resched) { + HMT_medium(); schedule(); check_pgt_cache(); } @@ -82,3 +132,5 @@ idled(); return 0; } + + diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/irq.c linuxppc64_2_4/arch/ppc64/kernel/irq.c --- linux-2.4.8-ac9/arch/ppc64/kernel/irq.c Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/kernel/irq.c Mon Aug 13 10:40:21 2001 @@ -526,7 +526,8 @@ { int cpu = smp_processor_id(); int irq; - unsigned long flags; + struct Paca * paca; + struct ItLpQueue * lpq; /* if(cpu) udbg_printf("Entering do_IRQ\n"); */ @@ -556,23 +557,23 @@ } /* if on iSeries partition */ else { + paca = (struct Paca *)mfspr(SPRG3); #ifdef CONFIG_SMP - if ( xPaca[cpu].xLpPacaPtr->xIpiCnt ) { - xPaca[cpu].xLpPacaPtr->xIpiCnt = 0; + if ( paca->xLpPaca.xIntDword.xFields.xIpiCnt ) { + paca->xLpPaca.xIntDword.xFields.xIpiCnt = 0; iSeries_smp_message_recv( regs ); } #endif /* CONFIG_SMP */ - __no_use_save_flags( &flags ); - __no_use_cli(); - lpEvent_count += ItLpQueue_process( &xItLpQueue, regs ); - __no_lpq_restore_flags( flags ); + lpq = paca->lpQueuePtr; + if ( lpq ) + lpEvent_count += ItLpQueue_process( lpq, regs ); } irq_exit(cpu); if ( _machine == _MACH_iSeries ) { - if ( xPaca[cpu].xLpPacaPtr->xDecrInt ) { - xPaca[cpu].xLpPacaPtr->xDecrInt = 0; + if ( paca->xLpPaca.xIntDword.xFields.xDecrInt ) { + paca->xLpPaca.xIntDword.xFields.xDecrInt = 0; /* Signal a fake decrementer interrupt */ timer_interrupt( regs ); } diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/lmb.c linuxppc64_2_4/arch/ppc64/kernel/lmb.c --- linux-2.4.8-ac9/arch/ppc64/kernel/lmb.c Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/kernel/lmb.c Wed Aug 15 15:36:41 2001 @@ -21,7 +21,8 @@ extern unsigned long klimit; extern unsigned long reloc_offset(void); -static long lmb_add_region(struct lmb_region *, unsigned long, unsigned long); + +static long lmb_add_region(struct lmb_region *, unsigned long, unsigned long, unsigned long); struct lmb lmb = { 0, @@ -39,7 +40,9 @@ rgn->region[r1].size += rgn->region[r2].size; for(i=r2; i < rgn->cnt-1 ;i++) { rgn->region[i].base = rgn->region[i+1].base; + rgn->region[i].physbase = rgn->region[i+1].physbase; rgn->region[i].size = rgn->region[i+1].size; + rgn->region[i].type = rgn->region[i+1].type; } rgn->cnt--; } @@ -57,11 +60,13 @@ */ _lmb->memory.region[0].base = 0; _lmb->memory.region[0].size = 0; + _lmb->memory.region[0].type = LMB_MEMORY_AREA; _lmb->memory.cnt = 1; /* Ditto. */ _lmb->reserved.region[0].base = 0; _lmb->reserved.region[0].size = 0; + _lmb->reserved.region[0].type = LMB_MEMORY_AREA; _lmb->reserved.cnt = 1; } @@ -69,14 +74,20 @@ void lmb_analyze(void) { - unsigned long i; - unsigned long size_mask = 0; + unsigned long i, physbase = 0; unsigned long total_size = 0; + unsigned long size_mask = 0; unsigned long offset = reloc_offset(); struct lmb *_lmb = PTRRELOC(&lmb); for(i=0; i < _lmb->memory.cnt ;i++) { unsigned long lmb_size = _lmb->memory.region[i].size; +#ifdef CONFIG_MSCHUNKS + _lmb->memory.region[i].physbase = physbase; + physbase += lmb_size; +#else + _lmb->memory.region[i].physbase = _lmb->memory.region[i].base; +#endif total_size += lmb_size; size_mask |= lmb_size; } @@ -92,7 +103,20 @@ struct lmb *_lmb = PTRRELOC(&lmb); struct lmb_region *_rgn = &(_lmb->memory); - return lmb_add_region(_rgn, base, size); + return lmb_add_region(_rgn, base, size, LMB_MEMORY_AREA); + +} + +/* This routine called with relocation disabled. */ +long +lmb_add_io(unsigned long base, unsigned long size) +{ + unsigned long offset = reloc_offset(); + struct lmb *_lmb = PTRRELOC(&lmb); + struct lmb_region *_rgn = &(_lmb->memory); + + return lmb_add_region(_rgn, base, size, LMB_IO_AREA); + } long @@ -102,20 +126,27 @@ struct lmb *_lmb = PTRRELOC(&lmb); struct lmb_region *_rgn = &(_lmb->reserved); - return lmb_add_region(_rgn, base, size); + return lmb_add_region(_rgn, base, size, LMB_MEMORY_AREA); } /* This routine called with relocation disabled. */ static long -lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size) +lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size, + unsigned long type) { unsigned long i, coalesced = 0; + long adjacent; /* First try and coalesce this LMB with another. */ for(i=0; i < rgn->cnt ;i++) { unsigned long rgnbase = rgn->region[i].base; unsigned long rgnsize = rgn->region[i].size; - long adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize); + unsigned long rgntype = rgn->region[i].type; + + if ( rgntype != type ) + continue; + + adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize); if ( adjacent > 0 ) { rgn->region[i].base -= size; rgn->region[i].physbase -= size; @@ -147,10 +178,12 @@ rgn->region[i+1].base = rgn->region[i].base; rgn->region[i+1].physbase = rgn->region[i].physbase; rgn->region[i+1].size = rgn->region[i].size; + rgn->region[i+1].type = rgn->region[i].type; } else { rgn->region[i+1].base = base; rgn->region[i+1].physbase = lmb_abs_to_phys(base); rgn->region[i+1].size = size; + rgn->region[i+1].type = type; break; } } @@ -181,15 +214,19 @@ { long i, j; unsigned long base; - unsigned long lmbbase, lmbsize; unsigned long offset = reloc_offset(); struct lmb *_lmb = PTRRELOC(&lmb); struct lmb_region *_mem = &(_lmb->memory); struct lmb_region *_rsv = &(_lmb->reserved); for(i=_mem->cnt-1; i >= 0 ;i--) { - lmbbase = _mem->region[i].base; - lmbsize = _mem->region[i].size; + unsigned long lmbbase = _mem->region[i].base; + unsigned long lmbsize = _mem->region[i].size; + unsigned long lmbtype = _mem->region[i].type; + + if ( lmbtype != LMB_MEMORY_AREA ) + continue; + base = _ALIGN_DOWN(lmbbase+lmbsize-size, align); while ( (lmbbase <= base) && @@ -201,16 +238,28 @@ break; } - if ( i < 0 ) { + if ( i < 0 ) return 0; - } - lmb_add_region(_rsv, base, size); + lmb_add_region(_rsv, base, size, LMB_MEMORY_AREA); return base; } unsigned long +lmb_phys_mem_size(void) +{ + unsigned long offset = reloc_offset(); + struct lmb *_lmb = PTRRELOC(&lmb); + struct lmb_region *_mem = &(_lmb->memory); + unsigned long idx = _mem->cnt-1; + unsigned long lastbase = _mem->region[idx].physbase; + unsigned long lastsize = _mem->region[idx].size; + + return (lastbase + lastsize); +} + +unsigned long lmb_end_of_DRAM(void) { unsigned long offset = reloc_offset(); @@ -248,4 +297,46 @@ return pa; } +void +lmb_dump(char *str) +{ + unsigned long i; + + udbg_printf("\nlmb_dump: %s\n", str); + udbg_printf(" debug = %s\n", + (lmb.debug) ? "TRUE" : "FALSE"); + udbg_printf(" memory.cnt = %d\n", + lmb.memory.cnt); + udbg_printf(" memory.size = 0x%lx\n", + lmb.memory.size); + udbg_printf(" memory.lcd_size = 0x%lx\n", + lmb.memory.lcd_size); + for(i=0; i < lmb.memory.cnt ;i++) { + udbg_printf(" memory.region[%d].base = 0x%lx\n", + i, lmb.memory.region[i].base); + udbg_printf(" .physbase = 0x%lx\n", + lmb.memory.region[i].physbase); + udbg_printf(" .size = 0x%lx\n", + lmb.memory.region[i].size); + udbg_printf(" .type = 0x%lx\n", + lmb.memory.region[i].type); + } + udbg_printf("\n"); + udbg_printf(" reserved.cnt = %d\n", + lmb.reserved.cnt); + udbg_printf(" reserved.size = 0x%lx\n", + lmb.reserved.size); + udbg_printf(" reserved.lcd_size = 0x%lx\n", + lmb.reserved.lcd_size); + for(i=0; i < lmb.reserved.cnt ;i++) { + udbg_printf(" reserved.region[%d].base = 0x%lx\n", + i, lmb.reserved.region[i].base); + udbg_printf(" .physbase = 0x%lx\n", + lmb.reserved.region[i].physbase); + udbg_printf(" .size = 0x%lx\n", + lmb.reserved.region[i].size); + udbg_printf(" .type = 0x%lx\n", + lmb.reserved.region[i].type); + } +} diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/mf.c linuxppc64_2_4/arch/ppc64/kernel/mf.c --- linux-2.4.8-ac9/arch/ppc64/kernel/mf.c Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/kernel/mf.c Wed Aug 15 08:38:20 2001 @@ -1019,45 +1019,6 @@ int mf_setRtcTime(unsigned long time) { -/* - char ceTime[12] = "\x00\x00\x00\x41\x00\x00\x00\x00\x00\x00\x00\x00"; - int rc = 0; - struct rtc_time tm; - u16 year; - u8 day, mon, hour, min, sec, y1, y2; - - to_tm(time, &tm); - - year = tm.tm_year; - y1 = (year >> 8) & 0x00FF; - y2 = year & 0x00FF; - - BIN_TO_BCD(tm.tm_sec); - BIN_TO_BCD(tm.tm_min); - BIN_TO_BCD(tm.tm_hour); - BIN_TO_BCD(tm.tm_mon); - BIN_TO_BCD(tm.tm_mday); - BIN_TO_BCD(y1); - BIN_TO_BCD(y2); - - year = y1 * 100 + y2; - day = tm.tm_mday; - mon = tm.tm_mon; - hour = tm.tm_hour; - min = tm.tm_min; - sec = tm.tm_sec; - - memcpy(ceTime + 4, &year, 2); - memcpy(ceTime + 6, &sec, 1); - memcpy(ceTime + 7, &min, 1); - memcpy(ceTime + 8, &hour, 1); - memcpy(ceTime + 10, &day, 1); - memcpy(ceTime + 11, &mon, 1); - - rc = signalCEMsg( ceTime, NULL ); - - return rc; -*/ struct rtc_time tm; to_tm(time, &tm); @@ -1067,7 +1028,7 @@ struct RtcTimeData { - volatile int xDone; + struct semaphore *xSemaphore; struct CeMsgData xCeMsg; int xRc; }; @@ -1079,7 +1040,7 @@ memcpy(&(rtc->xCeMsg), ceMsg, sizeof(rtc->xCeMsg)); rtc->xRc = 0; - rtc->xDone = 1; + up(rtc->xSemaphore); } static unsigned long lastsec = 1; @@ -1129,14 +1090,16 @@ int mf_getRtc( struct rtc_time * tm ) { - struct CeMsgCompleteData ceComplete; struct RtcTimeData rtcData; int rc = 0; + DECLARE_MUTEX_LOCKED(Semaphore); memset(&ceComplete, 0, sizeof(ceComplete)); memset(&rtcData, 0, sizeof(rtcData)); + rtcData.xSemaphore = &Semaphore; + ceComplete.xHdlr = &getRtcTimeComplete; ceComplete.xToken = (void *)&rtcData; @@ -1144,13 +1107,22 @@ if ( rc == 0 ) { - while( rtcData.xDone != 1 ) - { - udelay(10); - } + down(&Semaphore); if ( rtcData.xRc == 0) { + if ( ( rtcData.xCeMsg.xCEMsg[2] == 0xa9 ) || + ( rtcData.xCeMsg.xCEMsg[2] == 0xaf ) ) { + /* TOD clock is not set */ + tm->tm_sec = 1; + tm->tm_min = 1; + tm->tm_hour = 1; + tm->tm_mday = 10; + tm->tm_mon = 8; + tm->tm_year = 71; + mf_setRtc( tm ); + } + { u32 dataWord1 = *((u32 *)(rtcData.xCeMsg.xCEMsg+4)); u32 dataWord2 = *((u32 *)(rtcData.xCeMsg.xCEMsg+8)); u8 year = (dataWord1 >> 16 ) & 0x000000FF; @@ -1176,7 +1148,7 @@ tm->tm_mday = day; tm->tm_mon = mon; tm->tm_year = year; - + } } else { @@ -1189,6 +1161,10 @@ tm->tm_year = 52; } + tm->tm_wday = 0; + tm->tm_yday = 0; + tm->tm_isdst = 0; + } return rc; diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/misc.S linuxppc64_2_4/arch/ppc64/kernel/misc.S --- linux-2.4.8-ac9/arch/ppc64/kernel/misc.S Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/kernel/misc.S Tue Aug 14 23:24:17 2001 @@ -101,24 +101,22 @@ /* are we enabling interrupts? */ rlwinm. r0,r3,0,16,16 beq 1f - /* if so, check if there are any lost interrupts */ - LOADBASE(r7,ppc_n_lost_interrupts) - lwz r7,ppc_n_lost_interrupts@l(r7) - cmpi 0,r7,0 /* lost interrupts to process first? */ - bne- .do_lost_interrupts - /* Check for lost decrementer interrupts. - * (If decrementer popped while we were in the hypervisor) - * (calls timer_interrupt if so) + /* Check pending interrupts + * A decrementer, IPI or PMC interrupt may have occurred + * while we were in the hypervisor (which enables) */ - CHECKDECR(r4,r5) - bne- .do_fake_decrementer - /* Check for pending I/O Events. If no I/O events pending, - * then CR0 = "eq" and r4 == 0 - * (kills registers r5 and r6) + CHECKANYINT(r4,r5) + beq+ 1f + + /* + * Handle pending interrupts in interrupt context */ - CHECKLPQUEUE(r4,r5,r6) - bne- .do_lost_interrupts -1: sync + mtmsrd r3 + li r0,0x5555 + sc + blr +1: + sync mtmsrd r3 isync blr @@ -150,23 +148,22 @@ _GLOBAL(__no_use_sti) mfmsr r3 /* Get current state */ ori r3,r3,MSR_EE /* Turn on 'EE' bit */ - LOADBASE(r4,ppc_n_lost_interrupts) - lwz r4,ppc_n_lost_interrupts@l(r4) - cmpi 0,r4,0 /* lost interrupts to process first? */ - bne- .do_lost_interrupts - /* Check for lost decrementer interrupts. - * (If decrementer popped while we were in the hypervisor) - * (calls timer_interrupt if so) + /* Check for pending interrupts + * A decrementer, IPI or PMC interrupt may have occurred + * while we were in the hypervisor (which enables) */ - CHECKDECR(r4,r5) - bne- .do_fake_decrementer - /* Check for pending I/O events. If no I/O events pending, - * then CR0 = "eq" and R4 = 0 - * (kills registers r5 and r6) + CHECKANYINT(r4,r5) + beq+ 1f + + /* + * Handle pending interrupts in interrupt context */ - CHECKLPQUEUE(r4,r5,r6) - bne- .do_lost_interrupts + mtmsrd r3 + li r0,0x5555 + sc + blr +1: sync /* Some chip revs have problems here... */ mtmsrd r3 /* Update machine state */ blr @@ -175,21 +172,17 @@ * We were about to enable interrupts but we have to simulate * some interrupts that were lost by enable_irq first. */ -_GLOBAL(do_lost_interrupts) +_GLOBAL(do_fake_interrupt) mflr r0 std r0,16(r1) std r3,-8(r1) stdu r1,-(STACK_FRAME_OVERHEAD+16)(r1) 1: bl .fake_interrupt - LOADBASE(r4,ppc_n_lost_interrupts) - lwz r4,ppc_n_lost_interrupts@l(r4) - cmpi 0,r4,0 - bne- 1b - /* Check for pending I/O events. If no I/O events pending, - * then CR0 = "eq" and R4 = 0 - * (kills registers r5 and r6) + /* Check for pending interrupt + * A decrementer, IPI or PMC interrupt may have occurred + * while we were in the hypervisor (which enables) */ - CHECKLPQUEUE(r4,r5,r6) + CHECKANYINT(r4,r5) bne- 1b addi r1,r1,STACK_FRAME_OVERHEAD+16 ld r3,-8(r1) @@ -198,6 +191,7 @@ mtmsrd r3 blr +#if 0 _GLOBAL(do_fake_decrementer) mflr r0 std r0,16(r1) @@ -212,6 +206,7 @@ bne- .do_lost_interrupts mtmsrd r3 blr +#endif /* * complement mask on the msr then "or" some values on. @@ -252,7 +247,6 @@ /* * Write any modified data cache blocks out to memory * and invalidate the corresponding instruction cache blocks. - * This is a no-op on the 601. * * flush_icache_range(unsigned long start, unsigned long stop) * diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/mk_defs.c linuxppc64_2_4/arch/ppc64/kernel/mk_defs.c --- linux-2.4.8-ac9/arch/ppc64/kernel/mk_defs.c Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/kernel/mk_defs.c Mon Aug 13 10:16:24 2001 @@ -93,6 +93,7 @@ DEFINE(PACAR1, offsetof(struct Paca, xR1)); DEFINE(PACAR21, offsetof(struct Paca, xR21)); DEFINE(PACAR22, offsetof(struct Paca, xR22)); + DEFINE(PACACCR, offsetof(struct Paca, xCCR)); DEFINE(PACALPQUEUE, offsetof(struct Paca, lpQueuePtr)); DEFINE(PACALPPACA, offsetof(struct Paca, xLpPaca)); DEFINE(PACATOC, offsetof(struct Paca, xTOC)); @@ -100,8 +101,9 @@ DEFINE(LPREGSAV, offsetof(struct Paca, xRegSav)); DEFINE(LPPACASRR0, offsetof(struct ItLpPaca, xSavedSrr0)); DEFINE(LPPACASRR1, offsetof(struct ItLpPaca, xSavedSrr1)); - DEFINE(LPPACADECRINT, offsetof(struct ItLpPaca, xDecrInt)); - DEFINE(LPPACAIPIINT, offsetof(struct ItLpPaca, xIpiCnt)); + DEFINE(LPPACAANYINT, offsetof(struct ItLpPaca, xIntDword.xAnyInt)); + DEFINE(LPPACADECRINT, offsetof(struct ItLpPaca, xIntDword.xFields.xDecrInt)); + DEFINE(LPPACAIPIINT, offsetof(struct ItLpPaca, xIntDword.xFields.xIpiCnt)); DEFINE(LPQCUREVENTPTR, offsetof(struct ItLpQueue, xSlicCurEventPtr)); DEFINE(LPQOVERFLOW, offsetof(struct ItLpQueue, xPlicOverflowIntPending)); DEFINE(LPEVENTFLAGS, offsetof(struct HvLpEvent, xFlags)); diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/pacaData.c linuxppc64_2_4/arch/ppc64/kernel/pacaData.c --- linux-2.4.8-ac9/arch/ppc64/kernel/pacaData.c Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/kernel/pacaData.c Tue Aug 21 14:49:35 2001 @@ -39,8 +39,7 @@ 0, /* Kernel stack addr save */ \ (number), /* Paca Index */ \ 0, /* HW Proc Number */ \ - (start), /* Processor start */ \ - {0,0,0}, /* Resv */ \ + 0, /* CCR Save */ \ 0, /* MSR Save */ \ 0, /* LR Save */ \ 0, /* Pointer to thread */ \ @@ -52,21 +51,33 @@ 0, /* R1 Save */ \ (lpq), /* &xItLpQueue, */ \ {0,0,0,{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, SPIN_LOCK_UNLOCKED, 0}, /*xRtas */ \ - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /* Resv */ \ + (start), /* Processor start */ \ + {0,0,0,0,0,0,0}, /* Resv */ \ + 0, /* next_jiffy_update_tb */ \ + {0,0,0,0,0,0,0,0,0,0,0,0}, /* Resv */ \ { /* LpPaca */ \ xDesc: 0xd397d781, /* "LpPa" */ \ xSize: sizeof(struct ItLpPaca), /* */ \ + xFPRegsInUse: 1, \ + xDynProcStatus: 2, \ xEndOfQuantum: 0xffffffffffffffff /* */ \ }, \ { /* LpRegSave */ \ 0xd397d9e2, /* "LpRS" */ \ sizeof(struct ItLpRegSave) /* */ \ - } \ + }, \ + 0, /* pvr */ \ + 0, /* pgd_cache */ \ + 0, /* pmd_cache */ \ + 0, /* pte_cache */ \ + 0, /* pgtable_cache_sz */ \ + 0, /* prof_multiplier */ \ + 0 /* prof_counter */ \ } -struct Paca xPaca[maxPacas] = { +struct Paca xPaca[maxPacas] __page_aligned = { #ifdef CONFIG_PPC_ISERIES - PACAINITDATA( 0, 1, &xItLpQueue, 0x5000, 0xc000000000005000), + PACAINITDATA( 0, 1, &xItLpQueue, 0, 0xc000000000005000), #else PACAINITDATA( 0, 1, 0, 0x5000, 0xc000000000005000), #endif diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/pmc.c linuxppc64_2_4/arch/ppc64/kernel/pmc.c --- linux-2.4.8-ac9/arch/ppc64/kernel/pmc.c Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/kernel/pmc.c Tue Aug 14 14:55:53 2001 @@ -22,10 +22,7 @@ * End Change Activity */ -#ifndef _PMC_PROC_H -#include -#endif - +#include #include #include #include diff -uNr --exclude=CVS linux-2.4.8-ac9/arch/ppc64/kernel/pmc_proc.c linuxppc64_2_4/arch/ppc64/kernel/pmc_proc.c --- linux-2.4.8-ac9/arch/ppc64/kernel/pmc_proc.c Thu Aug 23 09:17:16 2001 +++ linuxppc64_2_4/arch/ppc64/kernel/pmc_proc.c Wed Dec 31 18:00:00 1969 @@ -1,650 +0,0 @@ -/* - * pmc_proc.c - * Copyright (C) 2001 Mike Corrigan IBM Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -/* Change Activity: */ -/* End Change Activity */ - -#ifndef _PMC_PROC_H -#include -#endif - -#include -#include -#include -#include - -#define MMCR0 795 -#define MMCR1 798 -#define MMCRA 786 -#define PMC1 787 -#define PMC2 788 -#define PMC3 789 -#define PMC4 790 -#define PMC5 791 -#define PMC6 792 -#define PMC7 793 -#define PMC8 794 - -static int proc_pmc_control_mode = 0; -#define PMC_CONTROL_CPI 1 -#define PMC_CONTROL_TLB 2 - -static struct proc_dir_entry *pmc_proc_root = NULL; - -int proc_get_lpevents( char *page, char **start, off_t off, int count, int *eof, void *data); -int proc_reset_lpevents( struct file *file, const char *buffer, unsigned long count, void *data); - -int proc_pmc_get_control( char *page, char **start, off_t off, int count, int *eof, void *data); -int proc_pmc_get_mmcr0( char *page, char **start, off_t off, int count, int *eof, void *data); -int proc_pmc_get_mmcr1( char *page, char **start, off_t off, int count, int *eof, void *data); -int proc_pmc_get_mmcra( char *page, char **start, off_t off, int count, int *eof, void *data); -int proc_pmc_get_pmc1( char *page, char **start, off_t off, int count, int *eof, void *data); -int proc_pmc_get_pmc2( char *page, char **start, off_t off, int count, int *eof, void *data); -int proc_pmc_get_pmc3( char *page, char **start, off_t off, int count, int *eof, void *data); -int proc_pmc_get_pmc4( char *page, char **start, off_t off, int count, int *eof, void *data); -int proc_pmc_get_pmc5( char *page, char **start, off_t off, int count, int *eof, void *data); -int proc_pmc_get_pmc6( char *page, char **start, off_t off, int count, int *eof, void *data); -int proc_pmc_get_pmc7( char *page, char **start, off_t off, int count, int *eof, void *data); -int proc_pmc_get_pmc8( char *page, char **start, off_t off, int count, int *eof, void *data); - -int proc_pmc_set_control( struct file *file, const char *buffer, unsigned long count, void *data); -int proc_pmc_set_mmcr0( struct file *file, const char *buffer, unsigned long count, void *data); -int proc_pmc_set_mmcr1( struct file *file, const char *buffer, unsigned long count, void *data); -int proc_pmc_set_mmcra( struct file *file, const char *buffer, unsigned long count, void *data); -int proc_pmc_set_pmc1( struct file *file, const char *buffer, unsigned long count, void *data); -int proc_pmc_set_pmc2( struct file *file, const char *buffer, unsigned long count, void *data); -int proc_pmc_set_pmc3( struct file *file, const char *buffer, unsigned long count, void *data); -int proc_pmc_set_pmc4( struct file *file, const char *buffer, unsigned long count, void *data); -int proc_pmc_set_pmc5( struct file *file, const char *buffer, unsigned long count, void *data); -int proc_pmc_set_pmc6( struct file *file, const char *buffer, unsigned long count, void *data); -int proc_pmc_set_pmc7( struct file *file, const char *buffer, unsigned long count, void *data); -int proc_pmc_set_pmc8( struct file *file, const char *buffer, unsigned long count, void *data); - -void pmc_proc_init(struct proc_dir_entry *iSeries_proc) -{ - struct proc_dir_entry *ent = NULL; - - ent = create_proc_entry("lpevents", S_IFREG|S_IRUGO, iSeries_proc); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_get_lpevents; - ent->write_proc = proc_reset_lpevents; - - pmc_proc_root = proc_mkdir("pmc", iSeries_proc); - if (!pmc_proc_root) return; - - ent = create_proc_entry("control", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_pmc_get_control; - ent->write_proc = proc_pmc_set_control; - - ent = create_proc_entry("mmcr0", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_pmc_get_mmcr0; - ent->write_proc = proc_pmc_set_mmcr0; - - ent = create_proc_entry("mmcr1", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_pmc_get_mmcr1; - ent->write_proc = proc_pmc_set_mmcr1; - - ent = create_proc_entry("mmcra", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_pmc_get_mmcra; - ent->write_proc = proc_pmc_set_mmcra; - - ent = create_proc_entry("pmc1", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_pmc_get_pmc1; - ent->write_proc = proc_pmc_set_pmc1; - - ent = create_proc_entry("pmc2", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_pmc_get_pmc2; - ent->write_proc = proc_pmc_set_pmc2; - - ent = create_proc_entry("pmc3", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_pmc_get_pmc3; - ent->write_proc = proc_pmc_set_pmc3; - - ent = create_proc_entry("pmc4", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_pmc_get_pmc4; - ent->write_proc = proc_pmc_set_pmc4; - - ent = create_proc_entry("pmc5", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_pmc_get_pmc5; - ent->write_proc = proc_pmc_set_pmc5; - - ent = create_proc_entry("pmc6", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_pmc_get_pmc6; - ent->write_proc = proc_pmc_set_pmc6; - - ent = create_proc_entry("pmc7", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_pmc_get_pmc7; - ent->write_proc = proc_pmc_set_pmc7; - - ent = create_proc_entry("pmc8", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_pmc_get_pmc8; - ent->write_proc = proc_pmc_set_pmc8; - - -} - -static int pmc_calc_metrics( char *page, char **start, off_t off, int count, int *eof, int len) -{ - if ( len <= off+count) - *eof = 1; - *start = page+off; - len -= off; - if ( len > count ) - len = count; - if ( len < 0 ) - len = 0; - return len; -} - -static char * lpEventTypes[9] = { - "Hypervisor\t\t", - "Machine Facilities\t", - "Session Manager\t", - "SPD I/O\t\t", - "Virtual Bus\t\t", - "PCI I/O\t\t", - "RIO I/O\t\t", - "Virtual Lan\t\t", - "Virtual I/O\t\t" - }; - - -int proc_get_lpevents -(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - unsigned i; - int len = 0; - - len += sprintf( page+len, "LpEventQueue 0\n" ); - len += sprintf( page+len, " events processed:\t%lu\n", - (unsigned long)xItLpQueue.xLpIntCount ); - for (i=0; i<9; ++i) { - len += sprintf( page+len, " %s %10lu\n", - lpEventTypes[i], - (unsigned long)xItLpQueue.xLpIntCountByType[i] ); - } - return pmc_calc_metrics( page, start, off, count, eof, len ); - -} - -int proc_reset_lpevents( struct file *file, const char *buffer, unsigned long count, void *data ) -{ - return count; -} - -int proc_pmc_get_control -(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - - if ( proc_pmc_control_mode == PMC_CONTROL_CPI ) { - unsigned long mach_cycles = mfspr( PMC5 ); - unsigned long inst_complete = mfspr( PMC4 ); - unsigned long inst_dispatch = mfspr( PMC3 ); - unsigned long thread_active_run = mfspr( PMC1 ); - unsigned long thread_active = mfspr( PMC2 ); - unsigned long cpi = 0; - unsigned long cpithou = 0; - unsigned long remain; - - if ( inst_complete ) { - cpi = thread_active_run / inst_complete; - remain = thread_active_run % inst_complete; - if ( inst_complete > 1000000 ) - cpithou = remain / ( inst_complete / 1000 ); - else - cpithou = ( remain * 1000 ) / inst_complete; - } - len += sprintf( page+len, "PMC CPI Mode\nRaw Counts\n" ); - len += sprintf( page+len, "machine cycles : %12lu\n", mach_cycles ); - len += sprintf( page+len, "thread active cycles : %12lu\n\n", thread_active ); - - len += sprintf( page+len, "instructions completed : %12lu\n", inst_complete ); - len += sprintf( page+len, "instructions dispatched : %12lu\n", inst_dispatch ); - len += sprintf( page+len, "thread active run cycles : %12lu\n", thread_active_run ); - - len += sprintf( page+len, "thread active run cycles/instructions completed\n" ); - len += sprintf( page+len, "CPI = %lu.%03lu\n", cpi, cpithou ); - - } - else if ( proc_pmc_control_mode == PMC_CONTROL_TLB ) { - len += sprintf( page+len, "PMC TLB Mode\n" ); - len += sprintf( page+len, "I-miss count : %12lu\n", mfspr( PMC1 ) ); - len += sprintf( page+len, "I-miss latency : %12lu\n", mfspr( PMC2 ) ); - len += sprintf( page+len, "D-miss count : %12lu\n", mfspr( PMC3 ) ); - len += sprintf( page+len, "D-miss latency : %12lu\n", mfspr( PMC4 ) ); - len += sprintf( page+len, "IERAT miss count : %12lu\n", mfspr( PMC5 ) ); - len += sprintf( page+len, "D-reference count : %12lu\n", mfspr( PMC6 ) ); - len += sprintf( page+len, "miss PTEs searched : %12lu\n", mfspr( PMC7 ) ); - len += sprintf( page+len, "miss >8 PTEs searched : %12lu\n", mfspr( PMC8 ) ); - } - /* IMPLEMENT ME */ - return pmc_calc_metrics( page, start, off, count, eof, len ); -} - -int proc_pmc_get_mmcr0 -(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = sprintf( page, "0x%08lx", mfspr(MMCR0) ); - return pmc_calc_metrics( page, start, off, count, eof, len ); -} - -int proc_pmc_get_mmcr1 -(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = sprintf( page, "0x%08lx", mfspr(MMCR1) ); - return pmc_calc_metrics( page, start, off, count, eof, len ); -} - -int proc_pmc_get_mmcra -(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = sprintf( page, "0x%08lx", mfspr(MMCRA) ); - return pmc_calc_metrics( page, start, off, count, eof, len ); -} - -int proc_pmc_get_pmc1 -(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = sprintf( page, "0x%08lx", mfspr(PMC1) ); - return pmc_calc_metrics( page, start, off, count, eof, len ); -} - -int proc_pmc_get_pmc2 -(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = sprintf( page, "0x%08lx", mfspr(PMC2) ); - return pmc_calc_metrics( page, start, off, count, eof, len ); -} - -int proc_pmc_get_pmc3 -(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = sprintf( page, "0x%08lx", mfspr(PMC3) ); - return pmc_calc_metrics( page, start, off, count, eof, len ); -} - -int proc_pmc_get_pmc4 -(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = sprintf( page, "0x%08lx", mfspr(PMC4) ); - return pmc_calc_metrics( page, start, off, count, eof, len ); -} - -int proc_pmc_get_pmc5 -(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = sprintf( page, "0x%08lx", mfspr(PMC5) ); - return pmc_calc_metrics( page, start, off, count, eof, len ); -} - -int proc_pmc_get_pmc6 -(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = sprintf( page, "0x%08lx", mfspr(PMC6) ); - return pmc_calc_metrics( page, start, off, count, eof, len ); -} - -int proc_pmc_get_pmc7 -(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = sprintf( page, "0x%08lx", mfspr(PMC7) ); - return pmc_calc_metrics( page, start, off, count, eof, len ); -} - -int proc_pmc_get_pmc8 -(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = sprintf( page, "0x%08lx", mfspr(PMC8) ); - return pmc_calc_metrics( page, start, off, count, eof, len ); -} - -unsigned long proc_pmc_conv_int( const char *buf, unsigned count ) -{ - const char * p; - char b0, b1; - unsigned v, multiplier, mult, i; - unsigned long val; - multiplier = 10; - p = buf; - if ( count >= 3 ) { - b0 = buf[0]; - b1 = buf[1]; - if ( ( b0 == '0' ) && - ( ( b1 == 'x' ) || ( b1 == 'X' ) ) ) { - p = buf + 2; - count -= 2; - multiplier = 16; - } - - } - val = 0; - for ( i=0; i= '0' ) && ( b0 <= '9' ) ) - v = b0 - '0'; - else if ( multiplier == 16 ) { - if ( ( b0 >= 'a' ) && ( b0 <= 'f' ) ) - v = b0 - 'a' + 10; - else if ( ( b0 >= 'A' ) && ( b0 <= 'F' ) ) - v = b0 - 'A' + 10; - else - mult = 1; - } - else - mult = 1; - val *= mult; - val += v; - } - - return val; - -} - -static inline void proc_pmc_stop(void) -{ - /* Freeze all counters, leave everything else alone */ - mtspr( MMCR0, mfspr( MMCR0 ) | 0x80000000 ); -} - -static inline void proc_pmc_start(void) -{ - /* Unfreeze all counters, leave everything else alone */ - mtspr( MMCR0, mfspr( MMCR0 ) & ~0x80000000 ); - -} - -static inline void proc_pmc_reset(void) -{ - /* Clear all the PMCs to zeros - * Assume a "stop" has already frozen the counters - * Clear all the PMCs - */ - mtspr( PMC1, 0 ); - mtspr( PMC2, 0 ); - mtspr( PMC3, 0 ); - mtspr( PMC4, 0 ); - mtspr( PMC5, 0 ); - mtspr( PMC6, 0 ); - mtspr( PMC7, 0 ); - mtspr( PMC8, 0 ); - -} - -static inline void proc_pmc_cpi(void) -{ - /* Configure the PMC registers to count cycles and instructions */ - /* so we can compute cpi */ - /* - * MMCRA[30] = 1 Don't count in wait state (CTRL[31]=0) - * MMCR0[6] = 1 Freeze counters when any overflow - * MMCR0[19:25] = 0x01 PMC1 counts Thread Active Run Cycles - * MMCR0[26:31] = 0x05 PMC2 counts Thread Active Cycles - * MMCR1[0:4] = 0x07 PMC3 counts Instructions Dispatched - * MMCR1[5:9] = 0x03 PMC4 counts Instructions Completed - * MMCR1[10:14] = 0x06 PMC5 counts Machine Cycles - * - */ - - proc_pmc_control_mode = PMC_CONTROL_CPI; - - // Indicate to hypervisor that we are using the PMCs - ((struct Paca *)mfspr(SPRG3))->xLpPacaPtr->xPMCRegsInUse = 1; - - // Freeze all counters - mtspr( MMCR0, 0x80000000 ); - mtspr( MMCR1, 0x00000000 ); - - // Clear all the PMCs - mtspr( PMC1, 0 ); - mtspr( PMC2, 0 ); - mtspr( PMC3, 0 ); - mtspr( PMC4, 0 ); - mtspr( PMC5, 0 ); - mtspr( PMC6, 0 ); - mtspr( PMC7, 0 ); - mtspr( PMC8, 0 ); - - /* Freeze counters in Wait State (CTRL[31]=0) */ - mtspr( MMCRA, 0x00000002 ); - - /* PMC3<-0x07, PMC4<-0x03, PMC5<-0x06 */ - mtspr( MMCR1, 0x38cc0000 ); - - mb(); - - /* PMC1<-0x01, PMC2<-0x05 - * Start all counters - */ - mtspr( MMCR0, 0x02000045 ); - -} - -static inline void proc_pmc_tlb(void) -{ - /* Configure the PMC registers to count tlb misses */ - /* - * MMCR0[6] = 1 Freeze counters when any overflow - * MMCR0[19:25] = 0x55 Group count - * PMC1 counts I misses - * PMC2 counts I miss duration (latency) - * PMC3 counts D misses - * PMC4 counts D miss duration (latency) - * PMC5 counts IERAT misses - * PMC6 counts D references (including PMC7) - * PMC7 counts miss PTEs searched - * PMC8 counts miss >8 PTEs searched - * - */ - - proc_pmc_control_mode = PMC_CONTROL_TLB; - - /* Indicate to hypervisor that we are using the PMCs */ - ((struct Paca *)mfspr(SPRG3))->xLpPacaPtr->xPMCRegsInUse = 1; - - /* Freeze all counters */ - mtspr( MMCR0, 0x80000000 ); - mtspr( MMCR1, 0x00000000 ); - - /* Clear all the PMCs */ - mtspr( PMC1, 0 ); - mtspr( PMC2, 0 ); - mtspr( PMC3, 0 ); - mtspr( PMC4, 0 ); - mtspr( PMC5, 0 ); - mtspr( PMC6, 0 ); - mtspr( PMC7, 0 ); - mtspr( PMC8, 0 ); - - mtspr( MMCRA, 0x00000000 ); - - mb(); - - /* PMC1<-0x55 - * Start all counters - */ - mtspr( MMCR0, 0x02001540 ); - -} - -int proc_pmc_set_control( struct file *file, const char *buffer, unsigned long count, void *data ) -{ - if ( ! strncmp( buffer, "stop", 4 ) ) - proc_pmc_stop(); - else if ( ! strncmp( buffer, "start", 5 ) ) - proc_pmc_start(); - else if ( ! strncmp( buffer, "reset", 5 ) ) - proc_pmc_reset(); - else if ( ! strncmp( buffer, "cpi", 3 ) ) - proc_pmc_cpi(); - else if ( ! strncmp( buffer, "tlb", 3 ) ) - proc_pmc_tlb(); - - /* IMPLEMENT ME */ - return count; -} - -int proc_pmc_set_mmcr0( struct file *file, const char *buffer, unsigned long count, void *data ) -{ - unsigned long v; - v = proc_pmc_conv_int( buffer, count ); - v = v & ~0x04000000; /* Don't allow interrupts for now */ - if ( v & ~0x80000000 ) /* Inform hypervisor we are using PMCs */ - ((struct Paca *)mfspr(SPRG3))->xLpPacaPtr->xPMCRegsInUse = 1; - else - ((struct Paca *)mfspr(SPRG3))->xLpPacaPtr->xPMCRegsInUse = 0; - mtspr( MMCR0, v ); - - return count; -} - -int proc_pmc_set_mmcr1( struct file *file, const char *buffer, unsigned long count, void *data ) -{ - unsigned long v; - v = proc_pmc_conv_int( buffer, count ); - mtspr( MMCR1, v ); - - return count; -} - -int proc_pmc_set_mmcra( struct file *file, const char *buffer, unsigned long count, void *data ) -{ - unsigned long v; - v = proc_pmc_conv_int( buffer, count ); - v = v & ~0x00008000; /* Don't allow interrupts for now */ - mtspr( MMCRA, v ); - - return count; -} - - -int proc_pmc_set_pmc1( struct file *file, const char *buffer, unsigned long count, void *data ) -{ - unsigned long v; - v = proc_pmc_conv_int( buffer, count ); - mtspr( PMC1, v ); - - return count; -} - -int proc_pmc_set_pmc2( struct file *file, const char *buffer, unsigned long count, void *data ) -{ - unsigned long v; - v = proc_pmc_conv_int( buffer, count ); - mtspr( PMC2, v ); - - return count; -} - -int proc_pmc_set_pmc3( struct file *file, const char *buffer, unsigned long count, void *data ) -{ - unsigned long v; - v = proc_pmc_conv_int( buffer, count ); - mtspr( PMC3, v ); - - return count; -} - -int proc_pmc_set_pmc4( struct file *file, const char *buffer, unsigned long count, void *data ) -{ - unsigned long v; - v = proc