diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/CREDITS linuxppc64_2_4/CREDITS
--- /kernels/64/linux-2.4.18-rc3/CREDITS Thu Feb 21 17:04:12 2002
+++ linuxppc64_2_4/CREDITS Thu Feb 21 21:01:59 2002
@@ -979,6 +979,14 @@
S: 80050-430 - Curitiba - Paraná
S: Brazil
+N: Tom Gall
+E: tom_gall@vnet.ibm.com
+E: tgall@rochcivictheatre.org
+D: ppc64, ppc
+S: 710 Walnut St
+S: Mantorville, MN 55955
+S: USA
+
N: Nigel Gamble
E: nigel@nrg.org
E: nigel@sgi.com
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/Documentation/Configure.help linuxppc64_2_4/Documentation/Configure.help
--- /kernels/64/linux-2.4.18-rc3/Documentation/Configure.help Thu Feb 21 17:04:12 2002
+++ linuxppc64_2_4/Documentation/Configure.help Thu Feb 21 20:53:15 2002
@@ -232,6 +232,13 @@
CPU and the single-board computers built around it, targeted for
network and embedded applications. For more information see the
Axis Communication site, .
+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
Multiquad support for NUMA systems
CONFIG_MULTIQUAD
@@ -15012,6 +15019,20 @@
hard drives and ADFS-formatted floppy disks. This is experimental
codes, so if you're unsure, say N.
+JFS filesystem support
+CONFIG_JFS_FS
+ This is a port of IBM's Journaled Filesystem . More information is
+ available in the file Documentation/filesystems/jfs.txt.
+
+ If you do not intend to use the JFS filesystem, say N.
+
+JFS Debugging
+CONFIG_JFS_DEBUG
+ If you are experiencing any problems with the JFS filesystem, say
+ Y here. This will result in additional debugging messages to be
+ written to the system log. Under normal circumstances, this
+ results in very little overhead.
+
/dev/pts file system for Unix98 PTYs
CONFIG_DEVPTS_FS
You should say Y here if you said Y to "Unix98 PTY support" above.
@@ -16181,6 +16202,19 @@
. The module will be called
isicom.o.
+IBM Multiport Serial Adapter
+CONFIG_ICOM
+ This driver is for a family of multiport serial adapters including
+ 2 port RVX (iSeries 2745), 2 port modem (iSeries
+ 2772) and 1 port RVX + 1 port modem (iSeries 2771). The
+ module is called iCom.o
+CONFIG_ICOM_MODEM_CC
+ This field entry enables the device driver to configure the modem
+ for appropriate operations based on country code. If you do not
+ have an internal modem card then a blank entry is recommended.
+ If you do have an internal modem card, look for the comment in iCom.c
+ indicating which value relates to your country.
+
Unix98 PTY support
CONFIG_UNIX98_PTYS
A pseudo terminal (PTY) is a software device consisting of two
@@ -20758,6 +20792,12 @@
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.
AltiVec kernel support
CONFIG_ALTIVEC
@@ -20821,6 +20861,16 @@
You may also want to compile the dma sound driver as a module and
have it autoloaded. The act of removing the module shuts down the
sound hardware for more power savings.
+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:
+
APM emulation
CONFIG_PMAC_APM_EMU
@@ -21109,6 +21159,12 @@
Date of Release: early 2001 (?)
End of life: -
URL:
+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 sparse
+ discontiguous memory. iSeries kernels need to have this on.
+ It is recommended that for pSeries hardware that you answer N.
ADB raw keycode support
CONFIG_MAC_ADBKEYCODES
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/Documentation/cachetlb.txt linuxppc64_2_4/Documentation/cachetlb.txt
--- /kernels/64/linux-2.4.18-rc3/Documentation/cachetlb.txt Fri Dec 21 11:41:53 2001
+++ linuxppc64_2_4/Documentation/cachetlb.txt Thu Feb 21 20:53:16 2002
@@ -260,8 +260,9 @@
Here is the new interface:
- void copy_user_page(void *to, void *from, unsigned long address)
- void clear_user_page(void *to, unsigned long address)
+ void copy_user_page(struct page *to, struct page *from,
+ unsigned long address)
+ void clear_user_page(struct page *to, unsigned long address)
These two routines store data in user anonymous or COW
pages. It allows a port to efficiently avoid D-cache alias
@@ -279,6 +280,11 @@
If D-cache aliasing is not an issue, these two routines may
simply call memcpy/memset directly and do nothing more.
+
+ There are default versions of these procedures supplied in
+ include/linux/highmem.h. If a port does not want to use the
+ default versions it should declare them and define the symbol
+ __HAVE_ARCH_USER_PAGE in include/asm/page.h.
void flush_dcache_page(struct page *page)
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/Documentation/filesystems/00-INDEX linuxppc64_2_4/Documentation/filesystems/00-INDEX
--- /kernels/64/linux-2.4.18-rc3/Documentation/filesystems/00-INDEX Wed Jun 20 13:10:27 2001
+++ linuxppc64_2_4/Documentation/filesystems/00-INDEX Thu Sep 13 14:29:38 2001
@@ -22,6 +22,8 @@
- info and mount options for the OS/2 HPFS.
isofs.txt
- info and mount options for the ISO 9660 (CDROM) filesystem.
+jfs.txt
+ - info and mount options for the JFS filesystem.
ncpfs.txt
- info on Novell Netware(tm) filesystem using NCP protocol.
ntfs.txt
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/Documentation/filesystems/changelog.jfs linuxppc64_2_4/Documentation/filesystems/changelog.jfs
--- /kernels/64/linux-2.4.18-rc3/Documentation/filesystems/changelog.jfs Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/Documentation/filesystems/changelog.jfs Wed Nov 14 10:19:35 2001
@@ -0,0 +1,726 @@
+IBM's Journaled File System (JFS) for Linux version 1.0.9
+Team members
+Steve Best sbest@us.ibm.com
+Dave Kleikamp shaggy@us.ibm.com
+Barry Arndt barndt@us.ibm.com
+
+
+Release November 9, 2001 (version 1.0.9)
+
+This is our forty-seventh release of IBM's Enterprise JFS technology port to Linux.
+Beta 1 was release 0.1.0 on 12/8/2000, Beta 2 was release 0.2.0 on 3/7/2001,
+Beta 3 was release 0.3.0 on 4/30/2001, and release 1.0.0 on 6/28/2001.
+
+The first drop on February 2, 2000 (jfs-0.0.1.tar.gz) had the following
+functionality (enough to allow other developers to evaluate and potentially
+contribute to this project):
+
+ - MKFS functional and able to format an existing or newly created partition for JFS.
+ - mount/unmount functional
+ - able to view the self(.) and parent (..) directories entries.
+
+The second drop on February 28, 2000 (jfs-0.0.2.tar.gz) had fixes for MKFS and the
+following utilities logredo, xchkdmp, xpeek are functional. The file system was able
+to mkdir, create files and directories were working (and rm, rmdir).
+
+The third drop on March 24, 2000 (jfs-0.0.3.tar.gz) provided read and write capability
+for the file system. Also, support for hard and soft links are functional.
+
+The fourth drop on March 29,2000 (jfs-0.0.4.tar.gz) provided rename capability for
+the file system and fixes for write problems.
+
+The fifth drop on April 6, 2000 (jfs-0.0.5.tar.gz) provided mknod capability for the
+file system.
+
+The sixth drop on April 21, 2000 (jfs-0.0.6.tar.gz) provided fixes for the file system
+and utilities.
+
+The seventh drop on May 11, 2000 (jfs-0.0.7.tar.gz) provided changes to the file system
+to be able to work on the development kernel 2.3.99-pre6. Drop 7 contains fixes for the
+file system to be built within the kernel.
+
+The eighth drop on June 20, 2000 (jfs-0.0.8.tar.gz) provided fixes for the file system
+and changes to the file system to be able to work on the development kernel 2.4.0-test1-ac21.
+In the utility area: fsck and logdump are functional.
+
+The ninth drop on July 13, 2000 (jfs-0.0.9.tar.gz) has the meta-data of the file system
+using the page cache. In the utility area: fixes for fsck.jfs and xpeek are included.
+
+The tenth drop on August 11, 2000 provided fixes for the file system
+and changes to the file system to be able to work on the development kernel 2.4.0-test5.
+In the utility area: fixes for fsck.jfs are included. The utility portion of extendfs has
+been ported (still need to port the file system portion for extendfs). Man pages have
+been written for the utilities. The compiler warnings have been removed from all of the
+utilities.
+
+The eleventh drop on September 1, 2000 provided fixes for the file system
+and changes to the file system to be able to work on the development kernel 2.4.0-test7.
+The utility portion of defrag has been ported (still need to port the file system portion
+for defrag).
+
+The twelfth drop on September 15, 2000 (jfs-0.0.12.tar.gz) provided the Transaction
+Manager Log I/O routines.
+
+The thirteenth drop on September 29, 2000 (jfs-0.0.13.tar.gz) provided case-sensitive
+support. In the utility area: fsck.jfs has the support for block/character special files.
+Note: The JFS partition must be formatted/reformatted using mkfs.jfs created by drop 13
+for case-sensitive to work.
+
+The fourteenth drop on October 4, 2000 (jfs-0.0.14.tar.gz) included a fix to the file
+system for not mounting a JFS partition if the size of the partition is > 4G on 2.2.x
+series of the kernel.
+
+The fifteenth drop on October 9, 2000 (jfs-0.0.15.tar.gz) included the Transaction
+Manager routines (Initialize, Begin, Locks, End). The file system has fixes and
+changes to the file system to be able to work on the development kernel 2.4.0-test9.
+The utility xchklog has been ported.
+
+The sixteenth drop on October 27, 2000 (jfs-0.0.16.tar.gz) included the Transaction
+Manager routines (Commit, Buffer Management, Abort). The file system and utilities
+have fixes included.
+
+The seventeenth drop on November 10, 2000 (jfs-0.0.17.tar.gz) has the transaction
+sub operations back into the file system operations. The file system is now journaling
+appropriate file system operations. The file system is temporary doing synchronous logging
+(which slows down operations that are logged) to make sure that the transaction processing
+is right. Asynchronous logging will be added shortly. The file system has fixes and changes
+to the file system to be able to work on the development kernel 2.4.0-test10.
+
+The eighteenth drop on November 15, 2000 (jfs-0.0.18.tar.gz) included fixes to the file
+system.
+
+The nineteenth drop on December 4, 2000 (jfs-0.0.19.tar.gz) is now doing asynchronous
+logging. The file system has fixes and changes to the file system to be able to work
+on the development kernel 2.4.0-test11.
+
+The twentieth drop on December 8, 2000 (jfs-0.1.0.tar.gz beta) included fixes to the file
+system.
+
+The twenty-first drop on December 14, 2000 (jfs-0.1.1.tar.gz) included a fsck fix
+to handle sparse files correctly. The file system has fixes and changes to the file
+system to be able to work on the development kernel 2.4.0-test12 and 2.2.18 kernel.
+
+The twenty-second drop on January 5, 2001 (jfs-0.1.2.tar.gz) included fixes to the
+file system. The file system has changes to able to work on the 2.4.0 kernel.
+
+The twenty-third drop on January 12, 2001 (jfs-0.1.3.tar.gz) included fixes to the
+file system. Fsck now supports fifo correctly.
+
+The twenty-fourth drop on January 26, 2001 (jfs-0.1.4.tar.gz) included fixes to the
+file system. The new feature in the file system is "Lazy Commit" which increases
+performance while going asynchronous logging. The main makefile for the utilities
+now has an install option.
+
+The twenty-fifth drop on February 7, 2001 (jfs-0.1.5.tar.gz) included fixes to the
+file system.
+
+The twenty-sixth drop on February 26, 2001 (jfs-0.1.6.tar.gz) included fixes to the
+file system. The log manager no longer uses the page cache for log pages, this
+eliminates dead-locks that were occurring in the log manager. The file system has
+general work done to remove SMP dead-lock problems. Fsck now supports default values
+passed by fstab correctly.
+
+The twenty-seventh drop on March 7, 2001 (beta 2) (jfs-0.2.0.tar.gz) included fixes to the
+file system. This drop contains jfsprogs.spec that can be used to create RPM for the
+JFS utilities. The file system has general work done to remove SMP and UP hang related problems.
+The file system performance has been increased by changes to extent inode cache.
+
+The twenty-eighth drop on March 21, 2001 (jfs-0.2.1.tar.gz) included fixes to the
+file system. The file system has been changed to use standard types.
+
+The twenty-ninth drop on April 2, 2001 (jfs-0.2.2.tar.gz) included fixes to the
+file system. The utilities have been changed to use standard types.
+
+The thirtieth drop on April 30, 2001 (jfs-0.3.0.tar.gz) included fixes to the
+file system. The rest of the utilities have been changed to use standard types.
+Both the file system and the utilities have been changed to use endian macros,
+so that JFS will now store the meta-data as little endian when running on all
+architectures, with this change you must re-format all of the JFS partitions
+using the new mkfs.jfs included in this drop, if you are running on a big-endian system.
+
+The thirty-first drop on May 9, 2001 (jfs-0.3.1.tar.gz) included fixes to the file
+system and the utilities.
+
+The thirty-second drop on May 18, 2001 (jfs-0.3.2-patch.tar.gz) included fixes to the file
+system and the utilities.
+
+The thirty-third drop on May 25, 2001 (jfs-0.3.3-patch.tar.gz) included fixes to the file
+system and the utilities.
+
+The thirty-fourth drop on June 8, 2001 (jfs-0.3.4-patch.tar.gz) included fixes to the
+file system and the utilities.
+
+The thirty-fifth drop on June 15, 2001 (jfs-0.3.5-patch.tar.gz) includes fixes to the
+file system and utilities.
+
+The thirty-sixth drop on June 22, 2001 (jfs-0.3.6-patch.tar.gz) includes fixes to the
+file system and utilities. The change made to the file system to fix the rm -rf problem
+is a disk layout change and with this change you must re-format all of the JFS partitions
+using the new mkfs.jfs included in this drop to have the rm -rf problem fixed.
+
+
+The thirty-seventh drop on June 25, 2001 (jfs-0.3.7-patch.tar.gz) includes fixes to the
+file system and utilities.
+
+The thirty-eighth drop on June 28, 2001 (jfs-1.0.0-patch.tar.gz) includes fixes to the
+file system and utilities.
+
+The thirty-ninth drop on July 10, 2001 (jfs-1.0.1-patch.tar.gz) includes fixes to the
+file system and utilities.
+
+The fortieth drop on August 3, 2001 (jfs-1.0.2-patch.tar.gz) includes fixes to the
+file system and utilities.
+
+The forty-first drop on August 20, 2001 (jfs-1.0.3-patch.tar.gz) includes fixes to the
+file system and utilities.
+
+The forty-second drop on August 31, 2001 (jfs-2.2-1.0.4-patch.tar.gz or
+jfs-2.4-1.0.4-patch.tar.gz) includes fixes to the file system and utilities.
+
+The forty-third drop on September 14, 2001 (jfs-2.2-1.0.5-patch.tar.gz or jfs-2.4-1.0.5-
+patch.tar.gz) includes fixes to the file system and utilities.
+
+The forty-fourth drop on September 28, 2001 (jfs-2.4-1.0.6-patch.tar.gz) includes fixes
+to the file system and utilities.
+
+The forty-fifth drop on October 10, 2001 (jfs-2.4-1.0.7-patch.tar.gz and
+jfsutils-1.0.7.tar.gz) includes fixes to the file system and utilities.
+
+The forty-sixth drop on October 17, 2001 (jfs-2.4-1.0.8-patch.tar.gz and
+jfsutils-1.0.8.tar.gz) includes fixes to the file system and utilities.
+
+The forty-seventh drop on November 9, 2001 (jfs-2.4-1.0.9-patch.tar.gz and
+jfsutils-1.0.9.tar.gz) includes fixes to the file system and utilities.
+
+
+Drop 47 has the temporary restriction that the block size must be 4K. MKFS.jfs defaults
+the block size to 4K.
+
+
+JFS today:
+
+
+- Utilities:
+ Function in drop 1
+ - MKFS.JFS builds on 2.2.12
+ - MKFS successfully formats a new partition for JFS
+
+ Function and Fixes in drop 2
+ - MKFS supports all parameters now
+ - MKFS has fixes from release pre-alpha 0.0.1
+ mkfs.jfs results in segmentation fault if no arguments are specified
+ mkfs.jfs hangs on invocation
+
+ - XPEEK, utility to PEEK and POKE JFS on-disk data/structures
+
+ Function and Fixes in drop 5
+ - MKFS.jfs has a fix to support -l option correctly.
+
+ Function and Fixes in drop 6
+ - libfs has compiler warning fixes and a bug fix
+
+ Function in drop 8
+ - fsck.jfs successfully checks and repairs a jfs partition
+ - logdump, utility that dumps the contents of the journal log.
+
+ Function and Fixes in drop 9
+ - fixes for fsck.jfs and xpeek have been done.
+
+ Function and Fixes in drop 10
+ - fixes for fsck.jfs
+ - man pages for utilities
+ - extendfs utility part has been ported (still need to port FS portion)
+ - compiler warnings have been removed.
+
+ Function and Fixes in drop 11
+ - defrag utility part has been ported (still need to port FS portion)
+
+ Function and Fixes in drop 13
+ - fsck.jfs supports block special files and character special files (Jitterbug problem #28)
+
+ Function and Fixes in drop 15
+ - ported xchklog utility, extracts a log from fsck.
+
+ Function and Fixes in drop 16
+ - fixes for fsck.jfs to handle case-sensitive support correctly (Jitterbug problem #36)
+ - cleanup changes for the utilities
+
+ Function and Fixes in drop 18
+ - cleanup changes for the utilities
+
+ Function and Fixes in drop 21
+ - fix in fsck to handle sparse files correctly
+
+ Function and Fixes in drop 23
+ - fix in fsck to handle fifo correctly
+
+ Function and Fixes in drop 24
+ - man pages updates for the utilities
+ - install option for utilities
+
+ Function and Fixes in drop 26
+ - man page updates for fsck
+ - fsck now supports default options passed by fstab correctly
+
+ Function and Fixes in drop 27
+ - new jfsprogs.spec file
+ - fix in fsck for hard links
+ - fix for unicode conversion problem
+
+ Function and Fixes in drop 29
+ - cleanup changes for the utilities
+ - Code cleanup to use standard types
+
+ Function and Fixes in drop 30
+ - added endian macros support
+ - Code cleanup to use standard types (part 2)
+ - mkfs now clears out the 1st 4k bytes of the partition
+
+ Function and Fixes in drop 31
+ - completed endian macros support needed for xpeek
+ - added socket support for fsck
+ - minor bug fixes
+
+ Function and Fixes in drop 32
+ - Remove the warning message from fsck when partition is mounted read-only
+
+ Function and Fixes in drop 33
+ - Fix fsck to handle mount read-only correctly
+ - Fix top level utilities makefile to be able to easily overide version of gcc compiler
+ - Man pages are now available in html format
+
+ Function and Fixes in drop 34
+ - fsck fix to handle pre-existing lost+found sub dir
+
+ Function and Fixes in drop 35
+ - updated fsck error handling
+ - updated mkfs config options and the man page for fsck
+
+ Function and Fixes in drop 36
+ - Fixed jitterbug # 10 rm -rf fails on a big directory
+
+ Function and Fixes in drop 38
+ - Fixed small logredo problem
+
+ Function and Fixes in drop 39 (1.0.1)
+ - Updated jfsprogs.spec file make it work on more distros
+ - Add force option to mkfs so the confirmation message isn't displayed
+ - Fixed fsck to handle index table on the root directory.
+ - Fixed error message displayed when partition was just created and haven't rebooted (jitterbug 130)
+ - Correctly place the built utilities in /sbin vs. /usr/sbin when using the make install
+ option.
+
+ Note: If you have used the make install option to copy over the utilities from a
+ previous release then you should remove the following JFS utilities (fsck.jfs, logdump,
+ logredo, mkfs.jfs, xchkdmp, xchklog, and xpeek) that could be in /usr/sbin. This release
+ of make install places the utilities in the correct location which is /sbin.
+
+ Function and Fixes in drop 40 (1.0.2)
+ - Fixed mkfs to display the correct error message if device name is not valid
+ or missing
+ - gzip the man pages and place /usr/share/man/man8
+ - Fixed mkfs to properly setup buf_ai (caused Bus error with mkfs on SPARC Linux)
+ - Fixed fsck to display path correctly
+
+ Function and Fixes in drop 41 (1.0.3)
+ - Fixed compiler warnings on 64 bit systems
+ - Created jfsutils package
+
+ Function and Fixes in drop 42 (1.0.4)
+ - Fixed typecast problem causing intermittent fsck failures on 64 bit hardware (jitterbug 159)
+ - Fixed pointer calculation problem causing intermittent fsck failures on 64 bit hardware
+ - Fixed compiler warnings on s/390 and IA64
+ - Fixed structure size mismatch between file system and utilities causing fsck problems when
+ large numbers of inodes are used
+ - Fixed seg fault in fsck when logging path lengths greater than 512 characters
+ - Fixed fsck printf format errors
+
+ Function and Fixes in drop 43 (1.0.5)
+ - Fixed jfsprogs.spec to handle utilities not being in the file systcem source tree
+ - Cleaned up include files
+ - Fixed inconsistencies in mkfs man, html pages
+
+ Function and Fixes in drop 44 (1.0.6)
+ - If fsck rebuilds root directory, reset di_next_index to 2
+ - fsck needs to process, validate inodes with size=0
+
+ Function and Fixes in drop 45 (1.0.7)
+ - improve fsck's 'mounted' detection
+ This will remove the message 'Cannot access file system description file to determine
+ mount status and file system type of /dev/device name'.
+ - improve utils' checking for fs type jfs
+ - replace __uX with uintX_t
+ - change fsck.jfs options to be similar to e2fsck
+ - set fsck.jfs default to automatically fix the file system
+
+Function and Fixes in drop 46 (1.0.8)
+ - install prefix support for jfsutils
+ - cleanup option handling make -y behave (jitterbug 177), -f override -p
+ - Add more informative error message when running fsck.jfs RO, (jitterbug 173)
+ - clean up remove carriage return after new line in messaging
+ - print mkfs.jfs version correctly
+
+Function and Fixes in drop 47 (1.0.9)
+ - don't print heartbeat if fsck.jfs output is redirected
+ - make mkfs.jfs options conform to mkfs, clean up parse code
+ - fix typo in mkfs.jfs man_html page
+ - allow xpeek to show us directory xtrees
+ - fix fsck.jfs infinite loop on big endian hardware (jitterbug 182)
+ - fix infinite loop when endian swapping bad directory tree page
+
+
+- JFS:
+ Function in drop 1
+ - builds on 2.2.12
+ - successfully MOUNTs & UMOUNTs
+ - limited READ capability (i.e. LS is operational)
+ - other system commands (i.e. DF, CHOWN, CHMOD, etc. working limited)
+
+ Function and Fixes in drop 2
+ - Write capabilities are operational
+ - MKDIR
+ - CREATE file
+ - RMDIR
+ - RM
+ - Problems fixed from release pre-alpha 0.0.1
+ using 2.2.14 jfs_imap.c:3004: `event' undeclared (first use in this function)
+
+ Function and Fixes in drop 3
+ - WRITE a file
+ - READ a file
+ - Support for hard and soft links
+
+ Function and Fixes in drop 4
+ - MV
+ - Executables can now be started from a jfs partition
+ - Problems while writing files have been fixed
+
+ Function and Fixes in drop 5
+ - added support for special files (mknod)
+ - alpha changes have been included
+
+ Function and Fixes in drop 6
+ - Jitterbug problem 9 du output is incorrect on jfs
+ - Jitterbug problem 11 unresolved symbol jfs_rwlock_lock on SMP build
+
+ Function and Fixes in drop 7
+ - moved JFS upto the 2.3.x development kernel (2.3.99-pre6)
+ - Jitterbug problem 14 can't build JFS within the kernel
+
+ Function and Fixes in drop 8
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test1-ac21)
+ - Jitterbug problem 17 undefined: jfs_rdwrlock_lock
+ - PowerPC build problem
+
+ Function and Fixes in drop 9
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test3)
+ - moved meta-data from buffer cache to page cache
+ - fixes for the file system are included
+
+ Function and Fixes in drop 10
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test5)
+ - fixes for the file system are included
+
+ Function and Fixes in drop 11
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test7)
+ - fixes for the file system are included
+ - start of journaling code has been included (jfs_txnmgr.h)
+ - WIP of log manager (jfs_logmgr.c)
+
+ Function and Fixes in drop 12
+ - Transaction Manager Log I/O -> Write log records is functional
+
+ Function and Fixes in drop 13
+ - case-sensitive support has been added
+
+ Function and Fixes in drop 14
+ - JFS mount error 22 is fixed (Jitterbug problem #30)
+
+ Function and Fixes in drop 15
+ - Following Transaction Manager routines are functional
+ Initialize -> Initialize transaction manager
+ Begin -> Start a transaction
+ Locks -> Acquire/release locks
+ End -> End a transaction
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test9)
+ - Fixed 2.2.x series block write problem.
+
+ Function and Fixes in drop 16
+ - Following Transaction Manager routines are functional
+ Commit -> Commit the transaction
+ Buffer Management -> Update inode, directory, extent
+ Abort -> Stop the commit from occurring
+ - File System build problem on 2.2.x series of the kernel (Jitterbug #35)
+ - Fixed case-sensitive bug in the filesystem (Jitterbug #36)
+
+
+ Function and Fixes in drop 17
+ - Added transaction sub operations back into the file system operations.
+ - The file system is now journaling appropriate file system operations.
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test10)
+
+ Function and Fixes in drop 18
+ - symlink fix
+ - inode corruption problem
+
+ Function and Fixes in drop 19
+ - Added asynchronous logging support back into the file system.
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test11)
+ - Fixes to transaction related hang problems.
+
+ Function and Fixes in drop 20
+ - Fix to remove memory on module cleanup
+
+ Function and Fixes in drop 21
+ - Fix so fsck doesn't report the message
+ Secondary file/directory allocation structure(2) is not a correct redundant copy of primary structure.
+ - Fix for setup of finish_aync_io
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test12)
+ - moved JFS upto the 2.2.18 kernel
+
+ Function and Fixes in drop 22
+
+ - moved JFS upto the 2.4.0 kernel
+ - Fix to do transaction processing for mknod correctly
+ - Fix for spinlock.h needed on 2.2.18 ppc
+
+ Function and Fixes in drop 23
+ - Fix for undefined BUG() in 2.2.x series
+ - Fix for 2.2 kernels, struct pipe_inode_info overlays the file system dependent portion of the inode structure.
+
+ Function and Fixes in drop 24
+ - rmmod jfs fix
+ - Implemented "Lazy Commit" - asynchronous logging enhancement to increase performance
+ - Removed ino_t from on-disk structures (fixes a mount problem)
+
+ Function and Fixes in drop 25
+ - Fix for deadlocks by putting IWRITE_LOCK/UNLOCK within jfs_delete_inode
+ - Fix to handle removing a link to an inode that isn't the last link.
+ - Fixes to general transaction processing SMP related hangs.
+
+ Function and Fixes in drop 26
+ - Fix for file writes on 2.2.x series of the kernel
+ - Change to log pages, so they no longer use the page cache.
+ - Fixes to general transaction processing SMP related dead-lock problems
+
+ Function and Fixes in drop 27
+ - Report error on read_metapage failure in jfs_readlink
+ - Report correct error in jfs_lookup if VFS fails to locate the inode
+ - Fix for a buffer overrun problem in jfs_readlink when compiled for linux-2.2
+ - Fix to support fsync call correctly (jitterbug #57)
+ - Fixes to general SMP related dead-lock problems
+ - Fix to define BUG() if 2.2 and !i386
+ - Fixes to general UP related hangs
+ - Changes to handling the inode extent cache increase the performance of the file system
+
+ Function and Fixes in drop 28
+ - Added ifdef IS_KIOBUFIO so JFS will be if kiobufs is in the kernel. Kiobufs has changed
+ the # of parameters for generic_make_request()
+ - Make jfsFYI a module parameter
+ insmod jfs.o jfsFYI=1 will turn on JFS FYI messages without having to recompile this
+ option is only supported on the 2.4.x kernel level.
+ - Defines cleanup_module() in terms of exit_jfs_fs()
+ - Fix to jfs_read_super, if get_empty_inode returns NULL cleanup correctly
+ - Code cleanup to use standard types
+
+
+ Function and Fixes in drop 29
+ - Fix for assert(iagp->wmap[extno] & mask); (line #2875) in jfs_imap while running dbench
+ - Fixed hang on scsi
+ - added /proc/fs/jfs/jfsFYI (2.4.* kernels only)
+ echo 1 > /proc/fs/jfs/jfsFYI ; Turns on very verbose output to syslog
+ echo 0 > /proc/fs/jfs/jfsFYI ; Turns it back off
+
+ Notes:
+ - IMPORTANT: If building jfs.o as a module on 2.2.* kernels, you will have to rebuild and
+ install the kernel to add wake_up_process to ksyms.c. Not needed on 2.4.* kernels.
+
+ Function and Fixes in drop 30
+ - Added endian macros support
+ - Fixed dbench hang
+ - jfs fails SPEC SFS validation on both NFSv2/NFSv3, fix to not add null-terminator to the symlink
+ value and accounting for it in the size.
+ - Fixed a bug where a casting of a 32 bit block # wasn't correct when a 64 bit value is needed.
+ xtLookup messages where display in the /var/log/messages (i.e of a message is below)
+ xtLookup: lstart (0x80000) >= size (0x80000)
+
+ Notes: release 0.3.0 requires a re-format of the JFS partition, if the system architecture is
+ big-endian (i.e. s/390, PowerPC, etc.)
+
+ Function and Fixes in drop 31
+ - Removed max hard links check (showed up during cp -a /usr /jfs/usr)
+ - Fixed inode writing hang could have showed up running (dbench, iozone, etc),
+ the change was to prevent a deadlock during inode writing.
+
+ Function and Fixes in drop 32
+ - Fix for assert(mp->count) jfs_metapage.c 675! report as hardlink problem in drop 31 (dtDeleteUp
+ was discarding the wrong metapage_t.
+ - Fix seg fault problem while creating hard links.
+ - Fixed dbench hang do to transaction locks not being freed.
+ - Added support to correctly handle read-only and remounting the file system.
+
+ Function and Fixes in drop 33
+
+ - Fixed statfs call to return the maximum number of inodes that JFS could allocate. (problem
+ reported as rpm exits with a (x) inodes needed message without installing the package).
+ - Fix to handle a case where a inode wasn't getting written to disk.
+ - Increase the performance of unlinking files.
+ - Fix to null terminate symlinks.
+ - General SMP fixes.
+
+ Function and Fixes in drop 34
+
+ - Fixed to remove a hang waiting on inode (jitterbug #73)
+ - Fixed dbench hang on SMP 8-way
+ - Fixed a log sync problem, improved performance with this fix
+
+ Function and Fixes in drop 35
+ - Increase the performance of unlinking files, most unlinks are done asynchronously now
+ - Fixed "XT_GETPAGE: xtree page corrupt" during creating files on nfs mounted partition
+
+ Function and Fixes in drop 36
+ - Fixed jitterbug # 10 rm -rf fails on a big directory
+
+ Notes: release 0.3.6 requires a re-format of the JFS partition, for the rm -rf problem
+ to be fixed.
+
+ Function and Fixes in drop 37
+ - Fixed find_entry called with index = 0 or 1 (jitterbug #126)
+ - Fixed the rm -rf case where if files weren't created sequential
+ then the rm -rf wasn't working correctly
+
+
+ Notes: If you used release 0.3.6 please re-format all JFS partitions, for the rm -rf problem
+ to be fixed.
+
+ Function and Fixes in drop 38
+ - Fixed some general log problems
+
+ Function and Fixes in drop 39 (1.0.1)
+ - Fixed hang during copying files on 2.2.x series
+ - Fixed TxLock compile problem
+ - Fixed to correctly update the number of blocks for directories (this was causing the FS
+ to show fsck error after compiling mozilla).
+ - Fixed to prevent old data from being written to disk from the page cache.
+
+ Function and Fixes in drop40 (1.0.2)
+ - Fixed multiple truncate hang
+ - Fixed hang on unlink a file and sync happening at the same time
+ - Improved handling of kmalloc error conditions
+ - Fixed hang in blk_get_queue and SMP deadlock: bh_end_io call generic_make_request
+ (jitterbug 145 and 146)
+ - stbl was not set correctly set in dtDelete
+ - changed trap to printk in dbAllocAG to avoid system hang
+
+ Function and Fixes in drop41 (1.0.3)
+ - Patch to move from previous release to latest release needs to update the version number in super.c
+ - Jitterbug problems (134,140,152) removing files have been fixed
+ - Set rc=ENOSPC if ialloc fails in jfs_create and jfs_mkdir
+ - Fixed jfs_txnmgr.c 775! assert
+ - Fixed jfs_txnmgr.c 884! assert(mp->nohomeok==0)
+ - Fix hang - prevent tblocks from being exhausted
+ - Fix oops trying to mount reiserfs
+ - Fail more gracefully in jfs_imap.c
+ - Print more information when char2uni fails
+ - Fix timing problem between Block map and metapage cache - jitterbug 139
+ - Code Cleanup (removed many ifdef's, obsolete code, ran code through indent) Mostly 2.4 tree
+ - Split source tree (Now have a separate source tree for 2.2, 2.4, and jfsutils)
+
+ Function and Fixes in drop42 (1.0.4)
+ - Fixed compiler warnings in the FS when building on 64 bits systems
+ - Fixed deadlock where jfsCommit hung in hold_metapage
+ - Fixed problems with remount
+ - Reserve metapages for jfsCommit thread
+ - Get rid of buggy invalidate_metapage & use discard_metapage
+ - Don't hand metapages to jfsIOthread (too many context switches) (jitterbug 125, bugzilla 238)
+ - Fix error message in jfs_strtoUCS
+
+ Function and Fixes in drop43 (1.0.5)
+ - Allow separate allocation of JFS-private superblock/inode data.
+ - Remove checks in namei.c that are already done by the VFS.
+ - Remove redundant mutex defines.
+ - Replace all occurrences of #include with #include
+ - Work around race condition in remount -fixes OOPS during shutdown
+ - Truncate large files incrementally ( affects directories too)
+
+ Function and Fixes in drop44 (1.0.6)
+ - Create jfs_incore.h which merges linux/jfs_fs.h, linux/jfs_fs_i.h, and jfs_fs_sb.h
+ - Create a configuration option to handle JFS_DEBUG define
+ - Fixed a few cases where positive error codes were returned to the VFS.
+ - Replace jfs_dir_read by generic_read_dir.
+ - jfs_fsync_inode is only called by jfs_fsync_file, merge the two and rename to jfs_fsync.
+ - Add a bunch of missing externs.
+ - jfs_rwlock_lock is unused, nuke it.
+ - Always use atomic set/test_bit operations to protect jfs_ip->cflag
+ - Combine jfs_ip->flag with jfs_ip->cflag
+ - Fixed minor format errors reported by fsck
+ - cflags should be long so bitops always works correctly
+ - Use GFP_NOFS for runtime memory allocations
+ - Support VM changes in 2.4.10 of the kernel
+ - Remove ifdefs supporting older 2.4 kernels. JFS now requires at least 2.4.3 or 2.4.2-ac2
+ - Simplify and remove one use of IWRITE_TRYLOCK
+ - jfs_truncate was not passing tid to xtTruncate
+ - removed obsolete extent_page workaround
+ - correct recovery from failed diAlloc call (disk full)
+ - In write_metapage, don't call commit_write if prepare_write failed
+
+ Function and Fixes in drop45 (1.0.7)
+ - cleanup remove IS_KIOBUFIO define.
+ - cleanup remove TRUNC_NO_TOSS define.
+ - have jFYI's use the name directly from dentry
+ - Remove nul _ALLOC and _FREE macros and also make spinlocks static.
+ - cleanup add externs where needed in the header files
+ - jfs_write_inode is a bad place to call iput. Also limit warnings.
+ - More truncate cleanup
+ - Truncate cleanup
+ - Add missing statics in jfs_metapage.c
+ - fsync fixes
+ - Clean up symlink code - use page_symlink_inode_operations
+ - unicode handling cleanup
+ - cleanup replace UniChar with wchar_t
+ - Get rid of CDLL_* macros - use list.h instead
+ - 2.4.11-prex mount problem Call new_inode instead of get_empty_inode
+ - use kernel min/max macros
+ - Add MODULE_LICENSE stub for older kernels
+ - IA64/gcc3 fixes
+ - Log Manager fixes, introduce __SLEEP_COND macro
+ - Mark superblock dirty when some errors detected (forcing fsck to be run).
+ - More robust remounting from r/o to r/w.
+ - Misc. cleanup add static where appropriate
+ - small cleanup in jfs_umount_rw
+ - add MODULE_ stuff
+ - Set *dropped_lock in alloc_metapage
+ - Get rid of unused log list
+ - cleanup jfs_imap.c to remove _OLD_STUFF and _NO_MORE_MOUNT_INODE defines
+ - Log manager cleanup
+ - Transaction manager cleanup
+ - correct memory allocations flags
+ - Better handling of iterative truncation
+ - Change continue to break, otherwise we don't re-acquire LAZY_LOCK
+
+ Function and Fixes in drop46 (1.0.8)
+ - Synclist was being built backwards causing logredo to quit too early
+ - jfs_compat.h needs to include module.h
+ - uncomment EXPORTS_NO_SYMBOLS in super.c
+ - Minor code cleanup
+ - xtree of zero-truncated file not being logged
+ - Fix logging on file truncate
+ - remove unused metapage fields
+
+ Function and Fixes in drop47 (1.0.9)
+ - Fix data corruption problem when creating files while deleting others. (jitterbug 183)
+ - Make sure all metadata is written before finalizing the log
+ - Fix serialization problem in shutdown by setting i_size of directory sooner.(bugzilla # 334)
+ - JFS should quit whining when special files are marked dirty during read-only mount.
+ - Must always check rc after DT_GETPAGE
+ - Add diExtendFS
+ - Removing defconfig from JFS source - not really needed
+
+
+Please send bugs, comments, cards and letters to linuxjfs@us.ibm.com.
+
+The JFS mailing list can be subscribed to by using the link labeled "Mail list Subscribe"
+at our web page http://oss.software.ibm.com/jfs/.
+
+
+
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/Documentation/filesystems/jfs.txt linuxppc64_2_4/Documentation/filesystems/jfs.txt
--- /kernels/64/linux-2.4.18-rc3/Documentation/filesystems/jfs.txt Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/Documentation/filesystems/jfs.txt Wed Nov 14 10:19:35 2001
@@ -0,0 +1,168 @@
+IBM's Journaled File System (JFS) for Linux version 1.0.9
+Team members
+Steve Best sbest@us.ibm.com
+Dave Kleikamp shaggy@us.ibm.com
+Barry Arndt barndt@us.ibm.com
+
+
+Release November 9, 2001 (version 1.0.9)
+
+This is our forty-seventh release of IBM's Enterprise JFS technology port to Linux.
+Beta 1 was release 0.1.0 on 12/8/2000, Beta 2 was release 0.2.0 on 3/7/2001,
+Beta 3 was release 0.3.0 on 4/30/2001, and release 1.0.0 on 6/28/2001.
+
+The changelog.jfs file contains detailed information of changes done in each source
+code drop.
+
+JFS has a source tree that can be built on 2.2.14 - 2.2.19 and 2.4.3 - 2.4.14
+kernel.org source trees.
+
+There is a anonymous cvs access available for the JFS tree. The steps below are
+what is needed to pull the JFS cvs tree from the oss.software.ibm.com server.
+
+id anoncvs
+password anoncvs
+
+To checkout 2.2.x series of the JFS files do the following:
+CVSROOT should be set to :pserver:anoncvs@oss.software.ibm.com:/usr/cvs/jfs
+cvs checkout linux-2.2.12
+
+To checkout 2.4.x series of the JFS files do the following:
+CVSROOT should be set to :pserver:anoncvs@oss.software.ibm.com:/usr/cvs/jfs
+cvs checkout linux24
+
+To checkout the JFS utilities do the following:
+CVSROOT should be set to :pserver:anoncvs@oss.software.ibm.com:/usr/cvs/jfs
+cvs checkout jfsutils
+
+The cvs tree contains the latest changes being done to JFS. To receive notification
+of commits to the cvs tree, please send e-mail to linuxjfs@us.ibm.com stating that
+you would like notifications sent to you.
+
+The jfs-2.4-1.0.9-patch.tar.gz file contains a readme and patch files for different
+levels of the 2.4 kernel. Please see the README in the jfs-2.4-1.0.9-patch.tar.gz
+file for help on applying the two patch files.
+
+Similarly jfs-2.2-1.0.5-patch.tar.gz contains a readme and patch files for
+different levels of the 2.2 kernel.
+
+The following files in the kernel source tree have been changed so JFS can be built.
+The jfs-2.4-1.0.9.tar.gz source tar ball now contains each of the files below with
+the extension of the kernel level it is associated with. As an example, there are now
+three Config.in files named Config.in-2.4.0, Config.in-2.4.5, and Config.in-2.4.7.
+
+Similarly, the jfs-2.2-1.0.5.tar.gz source tar ball contains the files
+Config.in-2.2.14, Config.in-2.2.16, and Config.in-2.2.18.
+
+If you use the tar ball to build JFS you must rename each of the kernel files to the
+file names listed below. The standard kernel from www.kernel.org is the source of the
+kernel files that are included in the jfs tar files.
+
+Note: Some of these files below do not need to be changed for the 2.4.x series of the
+kernel.
+
+In sub dir fs Config.in, Makefile, filesystem.c
+In sub dir fs/nls Config.in
+In sub dir arch/i386 defconfig
+In sub dir Documentation Configure.help
+In sub dir Documentation/filesystems 00-INDEX
+In sub dir include/linux fs.h
+In sub dir linux MAINTAINERS
+In sub dir linux/kernel/ksyms.c
+
+Please backup the above files before the JFS patch file is added to the kernel source
+tree. There are three new header files in the sub dir include/linux named jfs_fs.h,
+jfs_fs_i.h,and jfs_fs_sb.h. All other JFS files are located in the include/linux/jfs
+or fs/jfs sub dirs.
+
+Our development team has used the Linux kernel levels 2.2.14-2.2.19 and
+2.4.3 - 2.4.14 kernels with gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
+for our port so far. A goal of the JFS team is to have JFS run on all architectures
+that Linux supports, there is no architecture specific code in JFS. JFS has been run
+on the following architectures (x86, PowerPC, Alpha, s/390, ARM) so far.
+
+To make JFS build, during the "make config" step of building the kernel answer y to
+the Prompt for development and/or incomplete code/drivers in the Code maturity level
+options section. In the Filesystems section use the m for the answer to
+JFS filesystem support (experimental) (CONFIG_JFS_FS) [Y/m/n?]
+
+Note: If you are use JFS as module on the 2.2.x series of the kernel you must rebuild
+the kernel and run that rebuilt kernel for JFS to run. The reason for this change is
+that JFS needs to export symbols.
+
+Build in /usr/src/linux with the command:
+
+
+make modules
+make modules_install
+
+If you rebuild jfs.o after having mounted and unmounted a partition, "modprobe -r jfs"
+will unload the old module.
+
+For the file system debugging messages are being written to /var/log/messages.
+
+There are two ways to the build the JFS utilities, the first using the jfsprogs.spec
+file and the second way is to run make and then make install in the
+/jfsutils sub dir.
+
+To use the jfsprogs.spec located in sub dir jfsutils/SPECS you need to update
+the version of JFS in the spec file, also the corresponding jfsutils-x.x.x.tar.gz file
+must be in the SOURCES directory of your system. Now it's time to begin the build. First,
+change into the directory holding jfsprogs.spec file:
+
+cd /jfsutils/SPECS
+
+Next, start the build with a rpm -b command:
+
+rpm -ba jfsprogs.spec
+
+The a following the -b option directs RPM to perform all phases of the build process.
+
+
+The second way to build the utilities for JFS (mkfs, xpeek, logredo, xchkdmp, fsck, logdump, xchklog).
+
+Build in /jfsutils with the command:
+
+make
+make install
+
+One of results of this build is a program called mkfs.jfs.
+To format a JFS partition use the following command.
+
+ mkfs -t jfs device-name
+
+will result in the specified device being formatted.
+
+
+
+JFS TODO list:
+
+Plans for our near term development items
+
+ - Fix for 2.2 SMP kernel hangs
+ - get defrag capabilities operational in the FS
+ - get extendfs capabilities operational in the FS
+ - test EXTENDFS utility, for growing JFS partitions
+ - test defrag utility, calls file system to defrag the file system.
+ - add support for block sizes (512,1024,2048)
+ - add support for logfile on dedicated partition
+
+
+Longer term work items
+
+ - get access control list functionality operational
+ - get extended attributes functionality operational
+ - add quota support
+
+Please send bugs, comments, cards and letters to linuxjfs@us.ibm.com.
+
+The JFS mailing list can be subscribed to by using the link labeled "Mail list Subscribe"
+at our web page http://oss.software.ibm.com/jfs/.
+
+
+
+
+
+
+
+
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/MAINTAINERS linuxppc64_2_4/MAINTAINERS
--- /kernels/64/linux-2.4.18-rc3/MAINTAINERS Thu Feb 21 17:04:13 2002
+++ linuxppc64_2_4/MAINTAINERS Thu Feb 21 21:01:59 2002
@@ -844,6 +844,13 @@
W: http://sources.redhat.com/jffs2/
S: Maintained
+JFS FILESYSTEM
+P: Dave Kleikamp
+M: shaggy@austin.ibm.com
+L: jfs-discussion@oss.software.ibm.com
+W: http://oss.software.ibm.com/developerworks/opensource/jfs/
+S: Supported
+
JOYSTICK DRIVER
P: Vojtech Pavlik
M: vojtech@suse.cz
@@ -917,6 +924,13 @@
W: http://www.linuxppc.org/
L: linuxppc-dev@lists.linuxppc.org
S: Maintained
+
+LINUX FOR 64BIT POWERPC
+P: David Engebretsen
+M: engebret@us.ibm.com
+W: http://linuxppc64.org
+L: linuxppc64-dev@lists.linuxppc.org
+S: Supported
LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP Dynamic Disks)
P: Richard Russon (FlatCap)
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/Makefile linuxppc64_2_4/Makefile
--- /kernels/64/linux-2.4.18-rc3/Makefile Thu Feb 21 17:04:13 2002
+++ linuxppc64_2_4/Makefile Thu Feb 21 21:01:59 2002
@@ -5,7 +5,8 @@
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
-ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
+#ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
+ARCH := ppc64
KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g")
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
@@ -19,7 +20,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...)
@@ -152,6 +153,7 @@
DRIVERS-$(CONFIG_SCSI) += drivers/scsi/scsidrv.o
DRIVERS-$(CONFIG_FUSION_BOOT) += drivers/message/fusion/fusion.o
DRIVERS-$(CONFIG_IEEE1394) += drivers/ieee1394/ieee1394drv.o
+DRIVERS-$(CONFIG_PPC_ISERIES) += drivers/iseries/iseries.o
ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR)$(CONFIG_PARIDE_PCD),)
DRIVERS-y += drivers/cdrom/driver.o
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/Makefile linuxppc64_2_4/arch/ppc64/Makefile
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/Makefile Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/Makefile Fri Feb 22 11:52:05 2002
@@ -0,0 +1,80 @@
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" and "archdep" for cleaning up and making dependencies for
+# this architecture
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1994 by Linus Torvalds
+# Changes for PPC by Gary Thomas
+# Rewritten by Cort Dougan and Paul Mackerras
+# Adjusted for PPC64 by Tom Gall
+#
+
+KERNELLOAD =0xc000000000000000
+
+ifeq ($(shell uname -m),ppc64)
+CHECKS = checks
+endif
+
+LINKFLAGS = -T arch/ppc64/vmlinux.lds -Bstatic \
+ -e $(KERNELLOAD) -Ttext $(KERNELLOAD)
+CFLAGS := $(CFLAGS) -fsigned-char -msoft-float -pipe \
+ -Wno-uninitialized -mminimal-toc -fno-builtin
+CPP = $(CC) -E $(CFLAGS)
+
+
+HEAD := arch/ppc64/kernel/head.o
+
+ARCH_SUBDIRS = arch/ppc64/kernel arch/ppc64/mm arch/ppc64/lib
+SUBDIRS := $(SUBDIRS) $(ARCH_SUBDIRS)
+ARCHIVES := arch/ppc64/kernel/kernel.o arch/ppc64/mm/mm.o arch/ppc64/lib/lib.o $(ARCHIVES)
+CORE_FILES := arch/ppc64/kernel/kernel.o arch/ppc64/mm/mm.o arch/ppc64/lib/lib.o $(CORE_FILES)
+
+ifdef CONFIG_XMON
+SUBDIRS += arch/ppc64/xmon
+CORE_FILES += arch/ppc64/xmon/x.o
+endif
+ifdef CONFIG_KDB
+SUBDIRS += arch/ppc64/kdb
+CORE_FILES += arch/ppc64/kdb/kdba.o
+endif
+
+MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+
+checks:
+ @$(MAKE) -C arch/$(ARCH)/kernel checks
+
+ifdef CONFIG_PPC_PSERIES
+BOOT_TARGETS = zImage znetboot.initrd zImage.initrd
+endif
+
+ifdef CONFIG_PPC_ISERIES
+BOOT_TARGETS = vmlinux.sminitrd vmlinux.initrd vmlinux.sm
+endif
+
+$(BOOT_TARGETS): vmlinux
+ @$(MAKEBOOT) $@
+
+znetboot: vmlinux
+ifdef CONFIG_SMP
+ cp -f vmlinux /tftpboot/vmlinux.smp
+else
+ cp -f vmlinux /tftpboot/vmlinux
+endif
+ @$(MAKEBOOT) $@
+
+%_config: arch/ppc64/configs/%_defconfig
+ rm -f .config arch/ppc64/defconfig
+ cp -f arch/ppc64/configs/$(@:config=defconfig) arch/ppc64/defconfig
+
+archclean:
+ rm -f arch/ppc64/kernel/{ppc_defs.h,checks,mk_defs.s,mk_defs_out.c,mk_defs_tpl}
+ @$(MAKEBOOT) clean
+
+archmrproper:
+
+archdep:
+ $(MAKEBOOT) fastdep
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/Makefile linuxppc64_2_4/arch/ppc64/boot/Makefile
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/Makefile Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/boot/Makefile Mon Nov 5 11:20:37 2001
@@ -0,0 +1,129 @@
+# Makefile for making ELF bootable images for booting on CHRP
+# using Open Firmware.
+#
+# Geert Uytterhoeven September 1997
+#
+# Based on coffboot by Paul Mackerras
+# Simplified for ppc64 by Todd Inglett
+#
+# NOTE: this code is built for 32 bit in ELF32 format even though
+# it packages a 64 bit kernel. We do this to simplify the
+# bootloader and increase compatibility with OpenFirmware.
+#
+# To this end we need to define BOOTCC, etc, as the tools
+# needed to build the 32 bit image. These are normally HOSTCC,
+# but may be a third compiler if, for example, you are cross
+# compiling from an intel box. Once the 64bit ppc gcc is
+# stable it will probably simply be a compiler switch to
+# compile for 32bit mode.
+# To make it easier to setup a cross compiler,
+# CROSS32_COMPILE is setup as a prefix just like CROSS_COMPILE
+# in the toplevel makefile.
+
+CROSS32_COMPILE =
+#CROSS32_COMPILE = /usr/local/ppc/bin/powerpc-linux-
+
+BOOTCC = $(CROSS32_COMPILE)gcc
+BOOTCFLAGS = $(HOSTCFLAGS) -I$(HPATH)
+BOOTLD = $(CROSS32_COMPILE)ld
+BOOTAS = $(CROSS32_COMPILE)as
+BOOTAFLAGS = -D__ASSEMBLY__ $(HOSTCFLAGS)
+
+.c.o:
+ $(BOOTCC) $(BOOTCFLAGS) -c -o $*.o $<
+.S.o:
+ $(BOOTCC) $(BOOTAFLAGS) -traditional -c -o $*.o $<
+
+CFLAGS = $(CPPFLAGS) -O -fno-builtin -DSTDC_HEADERS
+LD_ARGS = -Ttext 0x00400000 -e _start
+
+OBJS = crt0.o start.o main.o zlib.o image.o imagesize.o
+#LIBS = $(TOPDIR)/lib/lib.a
+LIBS =
+
+ifeq ($(CONFIG_SMP),y)
+TFTPIMAGE=/tftpboot/zImage.chrp.smp
+else
+TFTPIMAGE=/tftpboot/zImage.chrp
+endif
+
+
+ifeq ($(CONFIG_PPC_ISERIES),y)
+all: vmlinux.sm
+else
+all: $(TOPDIR)/zImage
+endif
+
+
+znetboot: zImage
+ cp zImage $(TFTPIMAGE)
+
+
+ifeq ($(CONFIG_PPC_ISERIES),y)
+
+addSystemMap: addSystemMap.c
+ $(HOSTCC) $(HOSTCFLAGS) -o addSystemMap addSystemMap.c
+
+vmlinux.sm: $(TOPDIR)/vmlinux addSystemMap
+ ./addSystemMap $(TOPDIR)/System.map $(TOPDIR)/vmlinux vmlinux.sm
+
+
+addRamDisk: addRamDisk.c
+ $(HOSTCC) $(HOSTCFLAGS) -o addRamDisk addRamDisk.c
+
+vmlinux.initrd: $(TOPDIR)/vmlinux addRamDisk ramdisk.image.gz $(TOPDIR)/System.map
+ ./addRamDisk ramdisk.image.gz $(TOPDIR)/System.map $(TOPDIR)/vmlinux vmlinux.initrd
+
+vmlinux.sminitrd: vmlinux.sm addRamDisk ramdisk.image.gz $(TOPDIR)/System.map
+ ./addRamDisk ramdisk.image.gz $(TOPDIR)/System.map vmlinux.sm vmlinux.sminitrd
+
+endif
+
+
+znetboot.initrd: zImage.initrd
+ cp zImage.initrd $(TFTPIMAGE)
+
+floppy: zImage
+ mcopy zImage a:zImage
+
+piggyback: piggyback.c
+ $(HOSTCC) $(HOSTCFLAGS) -DKERNELBASE=$(KERNELBASE) -o piggyback piggyback.c
+
+addnote: addnote.c
+ $(HOSTCC) $(HOSTCFLAGS) -o addnote addnote.c
+
+image.o: piggyback vmlinux.gz
+ ./piggyback image < vmlinux.gz | $(BOOTAS) -o image.o
+
+sysmap.o: piggyback ../../../System.map
+ ./piggyback sysmap < ../../../System.map | $(BOOTAS) -o sysmap.o
+
+initrd.o: ramdisk.image.gz piggyback
+ ./piggyback initrd < ramdisk.image.gz | $(BOOTAS) -o initrd.o
+
+zImage: $(OBJS) no_initrd.o addnote
+ $(BOOTLD) $(LD_ARGS) -T zImage.lds -o $@ $(OBJS) no_initrd.o $(LIBS)
+ ./addnote $@
+
+zImage.initrd: $(OBJS) initrd.o addnote
+ $(BOOTLD) $(LD_ARGS) -T zImage.lds -o $@ $(OBJS) initrd.o $(LIBS)
+ ./addnote $@
+
+
+vmlinux.gz: $(TOPDIR)/vmlinux
+ $(OBJCOPY) -S -O binary $(TOPDIR)/vmlinux vmlinux
+ ls -l vmlinux | awk '{printf "/* generated -- do not edit! */\nint uncompressed_size = %d;\n", $$5}' > imagesize.c
+ $(CROSS_COMPILE)nm -n $(TOPDIR)/vmlinux | tail -1 | awk '{printf "long vmlinux_end = 0x%s;\n", substr($$1,8)}' >> imagesize.c
+ gzip -vf9 vmlinux
+
+imagesize.c: vmlinux.gz
+
+clean:
+ rm -f piggyback note addnote $(OBJS) zImage zImage.initrd vmlinux.gz no_initrd.o imagesize.c addSystemMap vmlinux.sm addRamDisk vmlinux.initrd vmlinux.sminitrd
+
+fastdep:
+ $(TOPDIR)/scripts/mkdep *.[Sch] > .depend
+
+dep:
+ $(CPP) $(CPPFLAGS) -M *.S *.c > .depend
+
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/addRamDisk.c linuxppc64_2_4/arch/ppc64/boot/addRamDisk.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/addRamDisk.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/boot/addRamDisk.c Thu Dec 13 22:42:13 2001
@@ -0,0 +1,301 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define ElfHeaderSize (64 * 1024)
+#define ElfPages (ElfHeaderSize / 4096)
+#define KERNELBASE (0xc000000000000000)
+
+void get4k(FILE *file, char *buf )
+{
+ unsigned j;
+ unsigned num = fread(buf, 1, 4096, file);
+ for ( j=num; j<4096; ++j )
+ buf[j] = 0;
+}
+
+void put4k(FILE *file, char *buf )
+{
+ fwrite(buf, 1, 4096, file);
+}
+
+void death(const char *msg, FILE *fdesc, const char *fname)
+{
+ printf(msg);
+ fclose(fdesc);
+ unlink(fname);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ char inbuf[4096];
+ FILE *ramDisk = NULL;
+ FILE *sysmap = NULL;
+ FILE *inputVmlinux = NULL;
+ FILE *outputVmlinux = NULL;
+
+ unsigned i = 0;
+ unsigned long ramFileLen = 0;
+ unsigned long ramLen = 0;
+ unsigned long roundR = 0;
+
+ unsigned long sysmapFileLen = 0;
+ unsigned long sysmapLen = 0;
+ unsigned long sysmapPages = 0;
+ char* ptr_end = NULL;
+ unsigned long offset_end = 0;
+
+ unsigned long kernelLen = 0;
+ unsigned long actualKernelLen = 0;
+ unsigned long round = 0;
+ unsigned long roundedKernelLen = 0;
+ unsigned long ramStartOffs = 0;
+ unsigned long ramPages = 0;
+ unsigned long roundedKernelPages = 0;
+ unsigned long hvReleaseData = 0;
+ u_int32_t eyeCatcher = 0xc8a5d9c4;
+ unsigned long naca = 0;
+ unsigned long xRamDisk = 0;
+ unsigned long xRamDiskSize = 0;
+ long padPages = 0;
+
+
+ if (argc < 2) {
+ printf("Name of RAM disk file missing.\n");
+ exit(1);
+ }
+
+ if (argc < 3) {
+ printf("Name of System Map input file is missing.\n");
+ exit(1);
+ }
+
+ if (argc < 4) {
+ printf("Name of vmlinux file missing.\n");
+ exit(1);
+ }
+
+ if (argc < 5) {
+ printf("Name of vmlinux output file missing.\n");
+ exit(1);
+ }
+
+
+ ramDisk = fopen(argv[1], "r");
+ if ( ! ramDisk ) {
+ printf("RAM disk file \"%s\" failed to open.\n", argv[1]);
+ exit(1);
+ }
+
+ sysmap = fopen(argv[2], "r");
+ if ( ! sysmap ) {
+ printf("System Map file \"%s\" failed to open.\n", argv[2]);
+ exit(1);
+ }
+
+ inputVmlinux = fopen(argv[3], "r");
+ if ( ! inputVmlinux ) {
+ printf("vmlinux file \"%s\" failed to open.\n", argv[3]);
+ exit(1);
+ }
+
+ outputVmlinux = fopen(argv[4], "w+");
+ if ( ! outputVmlinux ) {
+ printf("output vmlinux file \"%s\" failed to open.\n", argv[4]);
+ exit(1);
+ }
+
+
+
+ /* Input Vmlinux file */
+ fseek(inputVmlinux, 0, SEEK_END);
+ kernelLen = ftell(inputVmlinux);
+ fseek(inputVmlinux, 0, SEEK_SET);
+ printf("kernel file size = %d\n", kernelLen);
+ if ( kernelLen == 0 ) {
+ printf("You must have a linux kernel specified as argv[3]\n");
+ exit(1);
+ }
+
+ actualKernelLen = kernelLen - ElfHeaderSize;
+
+ printf("actual kernel length (minus ELF header) = %d\n", actualKernelLen);
+
+ round = actualKernelLen % 4096;
+ roundedKernelLen = actualKernelLen;
+ if ( round )
+ roundedKernelLen += (4096 - round);
+ printf("Vmlinux length rounded up to a 4k multiple = %ld/0x%lx \n", roundedKernelLen, roundedKernelLen);
+ roundedKernelPages = roundedKernelLen / 4096;
+ printf("Vmlinux pages to copy = %ld/0x%lx \n", roundedKernelPages, roundedKernelPages);
+
+
+
+ /* Input System Map file */
+ /* (needs to be processed simply to determine if we need to add pad pages due to the static variables not being included in the vmlinux) */
+ fseek(sysmap, 0, SEEK_END);
+ sysmapFileLen = ftell(sysmap);
+ fseek(sysmap, 0, SEEK_SET);
+ printf("%s file size = %ld/0x%lx \n", argv[2], sysmapFileLen, sysmapFileLen);
+
+ sysmapLen = sysmapFileLen;
+
+ roundR = 4096 - (sysmapLen % 4096);
+ if (roundR) {
+ printf("Rounding System Map file up to a multiple of 4096, adding %ld/0x%lx \n", roundR, roundR);
+ sysmapLen += roundR;
+ }
+ printf("Rounded System Map size is %ld/0x%lx \n", sysmapLen, sysmapLen);
+
+ /* Process the Sysmap file to determine where _end is */
+ sysmapPages = sysmapLen / 4096;
+ for (i=0; i
+#include
+#include
+#include
+#include
+#include
+
+void xlate( char * inb, char * trb, unsigned len )
+{
+ unsigned i;
+ for ( i=0; i> 4;
+ char c2 = c & 0xf;
+ if ( c1 > 9 )
+ c1 = c1 + 'A' - 10;
+ else
+ c1 = c1 + '0';
+ if ( c2 > 9 )
+ c2 = c2 + 'A' - 10;
+ else
+ c2 = c2 + '0';
+ *trb++ = c1;
+ *trb++ = c2;
+ }
+ *trb = 0;
+}
+
+#define ElfHeaderSize (64 * 1024)
+#define ElfPages (ElfHeaderSize / 4096)
+
+void get4k( /*istream *inf*/FILE *file, char *buf )
+{
+ unsigned j;
+ unsigned num = fread(buf, 1, 4096, file);
+ for ( j=num; j<4096; ++j )
+ buf[j] = 0;
+}
+
+void put4k( /*ostream *outf*/FILE *file, char *buf )
+{
+ fwrite(buf, 1, 4096, file);
+}
+
+int main(int argc, char **argv)
+{
+ char inbuf[4096];
+ FILE *sysmap = NULL;
+ char* ptr_end = NULL;
+ FILE *inputVmlinux = NULL;
+ FILE *outputVmlinux = NULL;
+ long i = 0;
+ unsigned long sysmapFileLen = 0;
+ unsigned long sysmapLen = 0;
+ unsigned long roundR = 0;
+ unsigned long kernelLen = 0;
+ unsigned long actualKernelLen = 0;
+ unsigned long round = 0;
+ unsigned long roundedKernelLen = 0;
+ unsigned long sysmapStartOffs = 0;
+ unsigned long sysmapPages = 0;
+ unsigned long roundedKernelPages = 0;
+ long padPages = 0;
+ if ( argc < 2 )
+ {
+ printf("Name of System Map file missing.\n");
+ exit(1);
+ }
+
+ if ( argc < 3 )
+ {
+ printf("Name of vmlinux file missing.\n");
+ exit(1);
+ }
+
+ if ( argc < 4 )
+ {
+ printf("Name of vmlinux output file missing.\n");
+ exit(1);
+ }
+
+ sysmap = fopen(argv[1], "r");
+ if ( ! sysmap )
+ {
+ printf("System Map file \"%s\" failed to open.\n", argv[1]);
+ exit(1);
+ }
+ inputVmlinux = fopen(argv[2], "r");
+ if ( ! inputVmlinux )
+ {
+ printf("vmlinux file \"%s\" failed to open.\n", argv[2]);
+ exit(1);
+ }
+ outputVmlinux = fopen(argv[3], "w");
+ if ( ! outputVmlinux )
+ {
+ printf("output vmlinux file \"%s\" failed to open.\n", argv[3]);
+ exit(1);
+ }
+
+
+
+ fseek(inputVmlinux, 0, SEEK_END);
+ kernelLen = ftell(inputVmlinux);
+ fseek(inputVmlinux, 0, SEEK_SET);
+ printf("kernel file size = %ld\n", kernelLen);
+ if ( kernelLen == 0 )
+ {
+ printf("You must have a linux kernel specified as argv[2]\n");
+ exit(1);
+ }
+
+
+ actualKernelLen = kernelLen - ElfHeaderSize;
+
+ printf("actual kernel length (minus ELF header) = %ld/%lxx \n", actualKernelLen, actualKernelLen);
+
+ round = actualKernelLen % 4096;
+ roundedKernelLen = actualKernelLen;
+ if ( round )
+ roundedKernelLen += (4096 - round);
+
+ printf("Kernel length rounded up to a 4k multiple = %ld/%lxx \n", roundedKernelLen, roundedKernelLen);
+ roundedKernelPages = roundedKernelLen / 4096;
+ printf("Kernel pages to copy = %ld/%lxx\n", roundedKernelPages, roundedKernelPages);
+
+
+
+ /* Sysmap file */
+ fseek(sysmap, 0, SEEK_END);
+ sysmapFileLen = ftell(sysmap);
+ fseek(sysmap, 0, SEEK_SET);
+ printf("%s file size = %ld\n", argv[1], sysmapFileLen);
+
+ sysmapLen = sysmapFileLen;
+
+ roundR = 4096 - (sysmapLen % 4096);
+ if (roundR)
+ {
+ printf("Rounding System Map file up to a multiple of 4096, adding %ld\n", roundR);
+ sysmapLen += roundR;
+ }
+ printf("Rounded System Map size is %ld\n", sysmapLen);
+
+ /* Process the Sysmap file to determine the true end of the kernel */
+ sysmapPages = sysmapLen / 4096;
+ printf("System map pages to copy = %ld\n", sysmapPages);
+ for (i=0; i
+#include
+#include
+#include
+
+char arch[] = "PowerPC";
+
+#define N_DESCR 6
+unsigned int descr[N_DESCR] = {
+ 0xffffffff, /* real-mode = true */
+ 0x00c00000, /* real-base, i.e. where we expect OF to be */
+ 0xffffffff, /* real-size */
+ 0xffffffff, /* virt-base */
+ 0xffffffff, /* virt-size */
+ 0x4000, /* load-base */
+};
+
+unsigned char buf[512];
+
+#define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1]))
+#define GET_32BE(off) ((GET_16BE(off) << 16) + GET_16BE((off)+2))
+
+#define PUT_16BE(off, v) (buf[off] = ((v) >> 8) & 0xff, \
+ buf[(off) + 1] = (v) & 0xff)
+#define PUT_32BE(off, v) (PUT_16BE((off), (v) >> 16), \
+ PUT_16BE((off) + 2, (v)))
+
+/* Structure of an ELF file */
+#define E_IDENT 0 /* ELF header */
+#define E_PHOFF 28
+#define E_PHENTSIZE 42
+#define E_PHNUM 44
+#define E_HSIZE 52 /* size of ELF header */
+
+#define EI_MAGIC 0 /* offsets in E_IDENT area */
+#define EI_CLASS 4
+#define EI_DATA 5
+
+#define PH_TYPE 0 /* ELF program header */
+#define PH_OFFSET 4
+#define PH_FILESZ 16
+#define PH_HSIZE 32 /* size of program header */
+
+#define PT_NOTE 4 /* Program header type = note */
+
+#define ELFCLASS32 1
+#define ELFDATA2MSB 2
+
+unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' };
+
+int
+main(int ac, char **av)
+{
+ int fd, n, i;
+ int ph, ps, np;
+ int nnote, ns;
+
+ if (ac != 2) {
+ fprintf(stderr, "Usage: %s elf-file\n", av[0]);
+ exit(1);
+ }
+ fd = open(av[1], O_RDWR);
+ if (fd < 0) {
+ perror(av[1]);
+ exit(1);
+ }
+
+ nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4;
+
+ n = read(fd, buf, sizeof(buf));
+ if (n < 0) {
+ perror("read");
+ exit(1);
+ }
+
+ if (n < E_HSIZE || memcmp(&buf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0)
+ goto notelf;
+
+ if (buf[E_IDENT+EI_CLASS] != ELFCLASS32
+ || buf[E_IDENT+EI_DATA] != ELFDATA2MSB) {
+ fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n",
+ av[1]);
+ exit(1);
+ }
+
+ ph = GET_32BE(E_PHOFF);
+ ps = GET_16BE(E_PHENTSIZE);
+ np = GET_16BE(E_PHNUM);
+ if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
+ goto notelf;
+ if (ph + (np + 1) * ps + nnote > n)
+ goto nospace;
+
+ for (i = 0; i < np; ++i) {
+ if (GET_32BE(ph + PH_TYPE) == PT_NOTE) {
+ fprintf(stderr, "%s already has a note entry\n",
+ av[1]);
+ exit(0);
+ }
+ ph += ps;
+ }
+
+ /* XXX check that the area we want to use is all zeroes */
+ for (i = 0; i < ps + nnote; ++i)
+ if (buf[ph + i] != 0)
+ goto nospace;
+
+ /* fill in the program header entry */
+ ns = ph + ps;
+ PUT_32BE(ph + PH_TYPE, PT_NOTE);
+ PUT_32BE(ph + PH_OFFSET, ns);
+ PUT_32BE(ph + PH_FILESZ, nnote);
+
+ /* fill in the note area we point to */
+ /* XXX we should probably make this a proper section */
+ PUT_32BE(ns, strlen(arch) + 1);
+ PUT_32BE(ns + 4, N_DESCR * 4);
+ PUT_32BE(ns + 8, 0x1275);
+ strcpy(&buf[ns + 12], arch);
+ ns += 12 + strlen(arch) + 1;
+ for (i = 0; i < N_DESCR; ++i)
+ PUT_32BE(ns + i * 4, descr[i]);
+
+ /* Update the number of program headers */
+ PUT_16BE(E_PHNUM, np + 1);
+
+ /* write back */
+ lseek(fd, (long) 0, SEEK_SET);
+ i = write(fd, buf, n);
+ if (i < 0) {
+ perror("write");
+ exit(1);
+ }
+ if (i < n) {
+ fprintf(stderr, "%s: write truncated\n", av[1]);
+ exit(1);
+ }
+
+ exit(0);
+
+ notelf:
+ fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]);
+ exit(1);
+
+ nospace:
+ fprintf(stderr, "sorry, I can't find space in %s to put the note\n",
+ av[0]);
+ exit(1);
+}
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/crt0.S linuxppc64_2_4/arch/ppc64/boot/crt0.S
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/crt0.S Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/boot/crt0.S Thu Sep 13 14:13:35 2001
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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.
+ *
+ * NOTE: this code runs in 32 bit mode and is packaged as ELF32.
+ */
+ .text
+ .globl _start
+_start:
+ lis 9,_start@h
+ lis 8,_etext@ha
+ addi 8,8,_etext@l
+1: dcbf 0,9
+ icbi 0,9
+ addi 9,9,0x20
+ cmplwi 0,9,8
+ blt 1b
+ sync
+ isync
+
+ ## Clear out the BSS as per ANSI C requirements
+
+ lis 7,_end@ha
+ addi 7,7,_end@l # r7 = &_end
+ lis 8,__bss_start@ha #
+ addi 8,8,__bss_start@l # r8 = &_bss_start
+
+ ## Determine how large an area, in number of words, to clear
+
+ subf 7,8,7 # r7 = &_end - &_bss_start + 1
+ addi 7,7,3 # r7 += 3
+ srwi. 7,7,2 # r7 = size in words.
+ beq 3f # If the size is zero, do not bother
+ addi 8,8,-4 # r8 -= 4
+ mtctr 7 # SPRN_CTR = number of words to clear
+ li 0,0 # r0 = 0
+2: stwu 0,4(8) # Clear out a word
+ bdnz 2b # If we are not done yet, keep clearing
+3:
+
+
+ b start
+
+
+
+/*
+ * Flush the dcache and invalidate the icache for a range of addresses.
+ *
+ * flush_cache(addr, len)
+ */
+ .global flush_cache
+flush_cache:
+ addi 4,4,0x1f /* len = (len + 0x1f) / 0x20 */
+ rlwinm. 4,4,27,5,31
+ mtctr 4
+ beqlr
+1: dcbf 0,3
+ icbi 0,3
+ addi 3,3,0x20
+ bdnz 1b
+ sync
+ isync
+ blr
+
+
+#define r0 0
+#define r3 3
+#define r4 4
+#define r5 5
+#define r6 6
+#define r7 7
+#define r8 8
+
+ .globl strcpy
+strcpy:
+ addi r5,r3,-1
+ addi r4,r4,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r5)
+ bne 1b
+ blr
+
+ .globl strncpy
+strncpy:
+ cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r6,r3,-1
+ addi r4,r4,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r6)
+ bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
+ blr
+
+ .globl strcat
+strcat:
+ addi r5,r3,-1
+ addi r4,r4,-1
+1: lbzu r0,1(r5)
+ cmpwi 0,r0,0
+ bne 1b
+ addi r5,r5,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r5)
+ bne 1b
+ blr
+
+ .globl strcmp
+strcmp:
+ addi r5,r3,-1
+ addi r4,r4,-1
+1: lbzu r3,1(r5)
+ cmpwi 1,r3,0
+ lbzu r0,1(r4)
+ subf. r3,r0,r3
+ beqlr 1
+ beq 1b
+ blr
+
+ .globl strlen
+strlen:
+ addi r4,r3,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ bne 1b
+ subf r3,r3,r4
+ blr
+
+ .globl memset
+memset:
+ rlwimi r4,r4,8,16,23
+ rlwimi r4,r4,16,0,15
+ addi r6,r3,-4
+ cmplwi 0,r5,4
+ blt 7f
+ stwu r4,4(r6)
+ beqlr
+ andi. r0,r6,3
+ add r5,r0,r5
+ subf r6,r0,r6
+ rlwinm r0,r5,32-2,2,31
+ mtctr r0
+ bdz 6f
+1: stwu r4,4(r6)
+ bdnz 1b
+6: andi. r5,r5,3
+7: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r6,r6,3
+8: stbu r4,1(r6)
+ bdnz 8b
+ blr
+
+ .globl bcopy
+bcopy:
+ mr r6,r3
+ mr r3,r4
+ mr r4,r6
+ b memcpy
+
+ .globl memmove
+memmove:
+ cmplw 0,r3,r4
+ bgt backwards_memcpy
+ /* fall through */
+
+ .globl memcpy
+memcpy:
+ rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
+ addi r6,r3,-4
+ addi r4,r4,-4
+ beq 2f /* if less than 8 bytes to do */
+ andi. r0,r6,3 /* get dest word aligned */
+ mtctr r7
+ bne 5f
+1: lwz r7,4(r4)
+ lwzu r8,8(r4)
+ stw r7,4(r6)
+ stwu r8,8(r6)
+ bdnz 1b
+ andi. r5,r5,7
+2: cmplwi 0,r5,4
+ blt 3f
+ lwzu r0,4(r4)
+ addi r5,r5,-4
+ stwu r0,4(r6)
+3: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r4,r4,3
+ addi r6,r6,3
+4: lbzu r0,1(r4)
+ stbu r0,1(r6)
+ bdnz 4b
+ blr
+5: subfic r0,r0,4
+ mtctr r0
+6: lbz r7,4(r4)
+ addi r4,r4,1
+ stb r7,4(r6)
+ addi r6,r6,1
+ bdnz 6b
+ subf r5,r0,r5
+ rlwinm. r7,r5,32-3,3,31
+ beq 2b
+ mtctr r7
+ b 1b
+
+ .globl backwards_memcpy
+backwards_memcpy:
+ rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
+ add r6,r3,r5
+ add r4,r4,r5
+ beq 2f
+ andi. r0,r6,3
+ mtctr r7
+ bne 5f
+1: lwz r7,-4(r4)
+ lwzu r8,-8(r4)
+ stw r7,-4(r6)
+ stwu r8,-8(r6)
+ bdnz 1b
+ andi. r5,r5,7
+2: cmplwi 0,r5,4
+ blt 3f
+ lwzu r0,-4(r4)
+ subi r5,r5,4
+ stwu r0,-4(r6)
+3: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+4: lbzu r0,-1(r4)
+ stbu r0,-1(r6)
+ bdnz 4b
+ blr
+5: mtctr r0
+6: lbzu r7,-1(r4)
+ stbu r7,-1(r6)
+ bdnz 6b
+ subf r5,r0,r5
+ rlwinm. r7,r5,32-3,3,31
+ beq 2b
+ mtctr r7
+ b 1b
+
+ .globl memcmp
+memcmp:
+ cmpwi 0,r5,0
+ blelr
+ mtctr r5
+ addi r6,r3,-1
+ addi r4,r4,-1
+1: lbzu r3,1(r6)
+ lbzu r0,1(r4)
+ subf. r3,r0,r3
+ bdnzt 2,1b
+ blr
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/main.c linuxppc64_2_4/arch/ppc64/boot/main.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/main.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/boot/main.c Wed Oct 31 08:32:02 2001
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * Updates for PPC64 by Todd Inglett & Dave Engebretsen.
+ *
+ * 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.
+ */
+#define __KERNEL__
+#include "zlib.h"
+#include
+#include
+#include
+
+void memmove(void *dst, void *im, int len);
+
+extern void *finddevice(const char *);
+extern int getprop(void *, const char *, void *, int);
+extern void printf(const char *fmt, ...);
+extern int sprintf(char *buf, const char *fmt, ...);
+void gunzip(void *, int, unsigned char *, int *);
+void *claim(unsigned int, unsigned int, unsigned int);
+void flush_cache(void *, int);
+void pause(void);
+static struct bi_record *make_bi_recs(unsigned long);
+
+#define RAM_START 0x00000000
+#define RAM_END (64<<20)
+
+#define BOOT_START ((unsigned long)_start)
+#define BOOT_END ((unsigned long)_end)
+
+/* Value picked to match that used by yaboot */
+#define PROG_START 0x01400000
+
+char *avail_ram;
+char *begin_avail, *end_avail;
+char *avail_high;
+unsigned int heap_use;
+unsigned int heap_max;
+unsigned long initrd_start = 0;
+unsigned long initrd_size = 0;
+
+extern char _end[];
+extern char image_data[];
+extern int image_len;
+extern char initrd_data[];
+extern int initrd_len;
+extern char sysmap_data[];
+extern int sysmap_len;
+extern int uncompressed_size;
+extern long vmlinux_end;
+
+static char scratch[128<<10]; /* 128kB of scratch space for gunzip */
+
+typedef void (*kernel_entry_t)( unsigned long,
+ unsigned long,
+ void *,
+ struct bi_record *);
+
+void
+chrpboot(unsigned long a1, unsigned long a2, void *prom)
+{
+ unsigned len;
+ void *dst = (void *)-1;
+ unsigned long claim_addr;
+ unsigned char *im;
+ extern char _start;
+ struct bi_record *bi_recs;
+ kernel_entry_t kernel_entry;
+
+ printf("chrpboot starting: loaded at 0x%x\n\r", (unsigned)&_start);
+
+ if (initrd_len) {
+ initrd_size = initrd_len;
+ initrd_start = (RAM_END - initrd_size) & ~0xFFF;
+ a1 = a2 = 0;
+ claim(initrd_start, RAM_END - initrd_start, 0);
+ printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r",
+ initrd_start, (unsigned long)initrd_data, initrd_size);
+ memcpy((void *)initrd_start, (void *)initrd_data, initrd_size);
+ }
+
+ im = image_data;
+ len = image_len;
+ uncompressed_size = PAGE_ALIGN(uncompressed_size);
+
+ for(claim_addr = PROG_START;
+ claim_addr <= PROG_START * 8;
+ claim_addr += 0x100000) {
+ printf(" trying: 0x%08lx\n\r", claim_addr);
+ dst = claim(claim_addr, uncompressed_size, 0);
+ if (dst != (void *)-1) break;
+ }
+ if (dst == (void *)-1) {
+ printf("claim error, can't allocate kernel memory\n\r");
+ return;
+ }
+
+ if (im[0] == 0x1f && im[1] == 0x8b) {
+ avail_ram = scratch;
+ begin_avail = avail_high = avail_ram;
+ end_avail = scratch + sizeof(scratch);
+ printf("gunzipping (0x%x <- 0x%x:0x%0x)...",
+ (unsigned)dst, (unsigned)im, (unsigned)im+len);
+ gunzip(dst, uncompressed_size, im, &len);
+ printf("done %u bytes\n\r", len);
+ printf("%u bytes of heap consumed, max in use %u\n\r",
+ (unsigned)(avail_high - begin_avail), heap_max);
+ } else {
+ memmove(dst, im, len);
+ }
+
+ flush_cache(dst, len);
+
+ bi_recs = make_bi_recs((unsigned long)dst + vmlinux_end);
+
+ kernel_entry = (kernel_entry_t)dst;
+ printf( "kernel:\n\r"
+ " entry addr = 0x%lx\n\r"
+ " a1 = 0x%lx,\n\r"
+ " a2 = 0x%lx,\n\r"
+ " prom = 0x%lx,\n\r"
+ " bi_recs = 0x%lx,\n\r",
+ (unsigned long)kernel_entry, a1, a2,
+ (unsigned long)prom, (unsigned long)bi_recs);
+
+ kernel_entry( a1, a2, prom, bi_recs );
+
+ printf("returned?\n\r");
+
+ pause();
+}
+
+static struct bi_record *
+make_bi_recs(unsigned long addr)
+{
+ struct bi_record *bi_recs;
+ struct bi_record *rec;
+
+ bi_recs = rec = bi_rec_init(addr);
+
+ rec = bi_rec_alloc(rec, 2);
+ rec->tag = BI_FIRST;
+ /* rec->data[0] = ...; # Written below before return */
+ /* rec->data[1] = ...; # Written below before return */
+
+ rec = bi_rec_alloc_bytes(rec, strlen("chrpboot")+1);
+ rec->tag = BI_BOOTLOADER_ID;
+ sprintf( (char *)rec->data, "chrpboot");
+
+ rec = bi_rec_alloc(rec, 2);
+ rec->tag = BI_MACHTYPE;
+ rec->data[0] = _MACH_pSeries;
+ rec->data[1] = 1;
+
+ if ( initrd_size > 0 ) {
+ rec = bi_rec_alloc(rec, 2);
+ rec->tag = BI_INITRD;
+ rec->data[0] = initrd_start;
+ rec->data[1] = initrd_size;
+ }
+
+#if 0
+ if ( sysmap_len > 0 ) {
+ rec = bi_rec_alloc(rec, 2);
+ rec->tag = BI_SYSMAP;
+ rec->data[0] = (unsigned long)sysmap_data;
+ rec->data[1] = sysmap_len;
+ }
+#endif
+
+ rec = bi_rec_alloc(rec, 1);
+ rec->tag = BI_LAST;
+ rec->data[0] = (bi_rec_field)bi_recs;
+
+ /* Save the _end_ address of the bi_rec's in the first bi_rec
+ * data field for easy access by the kernel.
+ */
+ bi_recs->data[0] = (bi_rec_field)rec;
+ bi_recs->data[1] = (bi_rec_field)rec + rec->size - (bi_rec_field)bi_recs;
+
+ return bi_recs;
+}
+
+struct memchunk {
+ unsigned int size;
+ unsigned int pad;
+ struct memchunk *next;
+};
+
+static struct memchunk *freechunks;
+
+void *zalloc(void *x, unsigned items, unsigned size)
+{
+ void *p;
+ struct memchunk **mpp, *mp;
+
+ size *= items;
+ size = _ALIGN(size, sizeof(struct memchunk));
+ heap_use += size;
+ if (heap_use > heap_max)
+ heap_max = heap_use;
+ for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) {
+ if (mp->size == size) {
+ *mpp = mp->next;
+ return mp;
+ }
+ }
+ p = avail_ram;
+ avail_ram += size;
+ if (avail_ram > avail_high)
+ avail_high = avail_ram;
+ if (avail_ram > end_avail) {
+ printf("oops... out of memory\n\r");
+ pause();
+ }
+ return p;
+}
+
+void zfree(void *x, void *addr, unsigned nb)
+{
+ struct memchunk *mp = addr;
+
+ nb = _ALIGN(nb, sizeof(struct memchunk));
+ heap_use -= nb;
+ if (avail_ram == addr + nb) {
+ avail_ram = addr;
+ return;
+ }
+ mp->size = nb;
+ mp->next = freechunks;
+ freechunks = mp;
+}
+
+#define HEAD_CRC 2
+#define EXTRA_FIELD 4
+#define ORIG_NAME 8
+#define COMMENT 0x10
+#define RESERVED 0xe0
+
+#define DEFLATED 8
+
+void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
+{
+ z_stream s;
+ int r, i, flags;
+
+ /* skip header */
+ i = 10;
+ flags = src[3];
+ if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+ printf("bad gzipped data\n\r");
+ exit();
+ }
+ if ((flags & EXTRA_FIELD) != 0)
+ i = 12 + src[10] + (src[11] << 8);
+ if ((flags & ORIG_NAME) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & COMMENT) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & HEAD_CRC) != 0)
+ i += 2;
+ if (i >= *lenp) {
+ printf("gunzip: ran out of data in header\n\r");
+ exit();
+ }
+
+ s.zalloc = zalloc;
+ s.zfree = zfree;
+ r = inflateInit2(&s, -MAX_WBITS);
+ if (r != Z_OK) {
+ printf("inflateInit2 returned %d\n\r", r);
+ exit();
+ }
+ s.next_in = src + i;
+ s.avail_in = *lenp - i;
+ s.next_out = dst;
+ s.avail_out = dstlen;
+ r = inflate(&s, Z_FINISH);
+ if (r != Z_OK && r != Z_STREAM_END) {
+ printf("inflate returned %d msg: %s\n\r", r, s.msg);
+ exit();
+ }
+ *lenp = s.next_out - (unsigned char *) dst;
+ inflateEnd(&s);
+}
+
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/mknote.c linuxppc64_2_4/arch/ppc64/boot/mknote.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/mknote.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/boot/mknote.c Fri May 4 17:13:58 2001
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Cort Dougan 1999.
+ *
+ * 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.
+ *
+ * Generate a note section as per the CHRP specification.
+ *
+ */
+
+#include
+
+#define PL(x) printf("%c%c%c%c", ((x)>>24)&0xff, ((x)>>16)&0xff, ((x)>>8)&0xff, (x)&0xff );
+
+int main(void)
+{
+/* header */
+ /* namesz */
+ PL(strlen("PowerPC")+1);
+ /* descrsz */
+ PL(6*4);
+ /* type */
+ PL(0x1275);
+ /* name */
+ printf("PowerPC"); printf("%c", 0);
+
+/* descriptor */
+ /* real-mode */
+ PL(0xffffffff);
+ /* real-base */
+ PL(0x00c00000);
+ /* real-size */
+ PL(0xffffffff);
+ /* virt-base */
+ PL(0xffffffff);
+ /* virt-size */
+ PL(0xffffffff);
+ /* load-base */
+ PL(0x4000);
+ return 0;
+}
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/no_initrd.c linuxppc64_2_4/arch/ppc64/boot/no_initrd.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/no_initrd.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/boot/no_initrd.c Fri May 4 17:13:58 2001
@@ -0,0 +1,2 @@
+char initrd_data[1];
+int initrd_len = 0;
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/piggyback.c linuxppc64_2_4/arch/ppc64/boot/piggyback.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/piggyback.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/boot/piggyback.c Fri May 4 17:13:58 2001
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2001 IBM Corp
+ *
+ * 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.
+ */
+#include
+#include
+
+extern long ce_exec_config[];
+
+int main(int argc, char *argv[])
+{
+ int i, cnt, pos, len;
+ unsigned int cksum, val;
+ unsigned char *lp;
+ unsigned char buf[8192];
+ if (argc != 2)
+ {
+ fprintf(stderr, "usage: %s name out-file\n",
+ argv[0]);
+ exit(1);
+ }
+ fprintf(stdout, "#\n");
+ fprintf(stdout, "# Miscellaneous data structures:\n");
+ fprintf(stdout, "# WARNING - this file is automatically generated!\n");
+ fprintf(stdout, "#\n");
+ fprintf(stdout, "\n");
+ fprintf(stdout, "\t.data\n");
+ fprintf(stdout, "\t.globl %s_data\n", argv[1]);
+ fprintf(stdout, "%s_data:\n", argv[1]);
+ pos = 0;
+ cksum = 0;
+ while ((len = read(0, buf, sizeof(buf))) > 0)
+ {
+ cnt = 0;
+ lp = (unsigned char *)buf;
+ len = (len + 3) & ~3; /* Round up to longwords */
+ for (i = 0; i < len; i += 4)
+ {
+ if (cnt == 0)
+ {
+ fprintf(stdout, "\t.long\t");
+ }
+ fprintf(stdout, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]);
+ val = *(unsigned long *)lp;
+ cksum ^= val;
+ lp += 4;
+ if (++cnt == 4)
+ {
+ cnt = 0;
+ fprintf(stdout, " # %x \n", pos+i-12);
+ fflush(stdout);
+ } else
+ {
+ fprintf(stdout, ",");
+ }
+ }
+ if (cnt)
+ {
+ fprintf(stdout, "0\n");
+ }
+ pos += len;
+ }
+ fprintf(stdout, "\t.globl %s_len\n", argv[1]);
+ fprintf(stdout, "%s_len:\t.long\t0x%x\n", argv[1], pos);
+ fflush(stdout);
+ fclose(stdout);
+ fprintf(stderr, "cksum = %x\n", cksum);
+ exit(0);
+}
+
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/start.c linuxppc64_2_4/arch/ppc64/boot/start.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/start.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/boot/start.c Thu Sep 13 14:13:35 2001
@@ -0,0 +1,654 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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.
+ */
+#include
+#include
+#include
+#include
+
+#include
+
+int (*prom)(void *);
+
+void *chosen_handle;
+void *stdin;
+void *stdout;
+void *stderr;
+
+void exit(void);
+void *finddevice(const char *name);
+int getprop(void *phandle, const char *name, void *buf, int buflen);
+void chrpboot(int a1, int a2, void *prom); /* in main.c */
+
+void printk(char *fmt, ...);
+
+void
+start(int a1, int a2, void *promptr)
+{
+ prom = (int (*)(void *)) promptr;
+ chosen_handle = finddevice("/chosen");
+ if (chosen_handle == (void *) -1)
+ exit();
+ if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
+ exit();
+ stderr = stdout;
+ if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
+ exit();
+
+ chrpboot(a1, a2, promptr);
+ for (;;)
+ exit();
+}
+
+int
+write(void *handle, void *ptr, int nb)
+{
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ void *ihandle;
+ void *addr;
+ int len;
+ int actual;
+ } args;
+
+ args.service = "write";
+ args.nargs = 3;
+ args.nret = 1;
+ args.ihandle = handle;
+ args.addr = ptr;
+ args.len = nb;
+ args.actual = -1;
+ (*prom)(&args);
+ return args.actual;
+}
+
+int
+read(void *handle, void *ptr, int nb)
+{
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ void *ihandle;
+ void *addr;
+ int len;
+ int actual;
+ } args;
+
+ args.service = "read";
+ args.nargs = 3;
+ args.nret = 1;
+ args.ihandle = handle;
+ args.addr = ptr;
+ args.len = nb;
+ args.actual = -1;
+ (*prom)(&args);
+ return args.actual;
+}
+
+void
+exit()
+{
+ struct prom_args {
+ char *service;
+ } args;
+
+ for (;;) {
+ args.service = "exit";
+ (*prom)(&args);
+ }
+}
+
+void
+pause(void)
+{
+ struct prom_args {
+ char *service;
+ } args;
+
+ args.service = "enter";
+ (*prom)(&args);
+}
+
+void *
+finddevice(const char *name)
+{
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ const char *devspec;
+ void *phandle;
+ } args;
+
+ args.service = "finddevice";
+ args.nargs = 1;
+ args.nret = 1;
+ args.devspec = name;
+ args.phandle = (void *) -1;
+ (*prom)(&args);
+ return args.phandle;
+}
+
+void *
+claim(unsigned long virt, unsigned long size, unsigned long align)
+{
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ unsigned int virt;
+ unsigned int size;
+ unsigned int align;
+ void *ret;
+ } args;
+
+ args.service = "claim";
+ args.nargs = 3;
+ args.nret = 1;
+ args.virt = virt;
+ args.size = size;
+ args.align = align;
+ (*prom)(&args);
+ return args.ret;
+}
+
+int
+getprop(void *phandle, const char *name, void *buf, int buflen)
+{
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ void *phandle;
+ const char *name;
+ void *buf;
+ int buflen;
+ int size;
+ } args;
+
+ args.service = "getprop";
+ args.nargs = 4;
+ args.nret = 1;
+ args.phandle = phandle;
+ args.name = name;
+ args.buf = buf;
+ args.buflen = buflen;
+ args.size = -1;
+ (*prom)(&args);
+ return args.size;
+}
+
+int
+putc(int c, void *f)
+{
+ char ch = c;
+
+ if (c == '\n')
+ putc('\r', f);
+ return write(f, &ch, 1) == 1? c: -1;
+}
+
+int
+putchar(int c)
+{
+ return putc(c, stdout);
+}
+
+int
+fputs(char *str, void *f)
+{
+ int n = strlen(str);
+
+ return write(f, str, n) == n? 0: -1;
+}
+
+int
+readchar(void)
+{
+ char ch;
+
+ for (;;) {
+ switch (read(stdin, &ch, 1)) {
+ case 1:
+ return ch;
+ case -1:
+ printk("read(stdin) returned -1\r\n");
+ return -1;
+ }
+ }
+}
+
+static char line[256];
+static char *lineptr;
+static int lineleft;
+
+int
+getchar(void)
+{
+ int c;
+
+ if (lineleft == 0) {
+ lineptr = line;
+ for (;;) {
+ c = readchar();
+ if (c == -1 || c == 4)
+ break;
+ if (c == '\r' || c == '\n') {
+ *lineptr++ = '\n';
+ putchar('\n');
+ break;
+ }
+ switch (c) {
+ case 0177:
+ case '\b':
+ if (lineptr > line) {
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+ --lineptr;
+ }
+ break;
+ case 'U' & 0x1F:
+ while (lineptr > line) {
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+ --lineptr;
+ }
+ break;
+ default:
+ if (lineptr >= &line[sizeof(line) - 1])
+ putchar('\a');
+ else {
+ putchar(c);
+ *lineptr++ = c;
+ }
+ }
+ }
+ lineleft = lineptr - line;
+ lineptr = line;
+ }
+ if (lineleft == 0)
+ return -1;
+ --lineleft;
+ return *lineptr++;
+}
+
+
+
+/* String functions lifted from lib/vsprintf.c and lib/ctype.c */
+unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
+
+size_t strnlen(const char * s, size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+
+unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
+{
+ unsigned long result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if ((*cp == 'x') && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ }
+ while (isxdigit(*cp) &&
+ (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+long simple_strtol(const char *cp,char **endp,unsigned int base)
+{
+ if(*cp=='-')
+ return -simple_strtoul(cp+1,endp,base);
+ return simple_strtoul(cp,endp,base);
+}
+
+static int skip_atoi(const char **s)
+{
+ int i=0;
+
+ while (isdigit(**s))
+ i = i*10 + *((*s)++) - '0';
+ return i;
+}
+
+#define ZEROPAD 1 /* pad with zero */
+#define SIGN 2 /* unsigned/signed long */
+#define PLUS 4 /* show plus */
+#define SPACE 8 /* space if plus */
+#define LEFT 16 /* left justified */
+#define SPECIAL 32 /* 0x */
+#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
+
+static char * number(char * str, long long num, int base, int size, int precision, int type)
+{
+ char c,sign,tmp[66];
+ const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
+ int i;
+
+ if (type & LARGE)
+ digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+ if (base < 2 || base > 36)
+ return 0;
+ c = (type & ZEROPAD) ? '0' : ' ';
+ sign = 0;
+ if (type & SIGN) {
+ if (num < 0) {
+ sign = '-';
+ num = -num;
+ size--;
+ } else if (type & PLUS) {
+ sign = '+';
+ size--;
+ } else if (type & SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & SPECIAL) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++]='0';
+ else while (num != 0)
+ tmp[i++] = digits[do_div(num,base)];
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT)))
+ while(size-->0)
+ *str++ = ' ';
+ if (sign)
+ *str++ = sign;
+ if (type & SPECIAL) {
+ if (base==8)
+ *str++ = '0';
+ else if (base==16) {
+ *str++ = '0';
+ *str++ = digits[33];
+ }
+ }
+ if (!(type & LEFT))
+ while (size-- > 0)
+ *str++ = c;
+ while (i < precision--)
+ *str++ = '0';
+ while (i-- > 0)
+ *str++ = tmp[i];
+ while (size-- > 0)
+ *str++ = ' ';
+ return str;
+}
+
+/* Forward decl. needed for IP address printing stuff... */
+int sprintf(char * buf, const char *fmt, ...);
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ int len;
+ unsigned long long num;
+ int i, base;
+ char * str;
+ const char *s;
+
+ int flags; /* flags to number() */
+
+ int field_width; /* width of output field */
+ int precision; /* min. # of digits for integers; max
+ number of chars for from string */
+ int qualifier; /* 'h', 'l', or 'L' for integer fields */
+ /* 'z' support added 23/7/1999 S.H. */
+ /* 'z' changed to 'Z' --davidm 1/25/99 */
+
+
+ for (str=buf ; *fmt ; ++fmt) {
+ if (*fmt != '%') {
+ *str++ = *fmt;
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+ repeat:
+ ++fmt; /* this also skips first '%' */
+ switch (*fmt) {
+ case '-': flags |= LEFT; goto repeat;
+ case '+': flags |= PLUS; goto repeat;
+ case ' ': flags |= SPACE; goto repeat;
+ case '#': flags |= SPECIAL; goto repeat;
+ case '0': flags |= ZEROPAD; goto repeat;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (isdigit(*fmt))
+ field_width = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ field_width = va_arg(args, int);
+ if (field_width < 0) {
+ field_width = -field_width;
+ flags |= LEFT;
+ }
+ }
+
+ /* get the precision */
+ precision = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (isdigit(*fmt))
+ precision = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ precision = va_arg(args, int);
+ }
+ if (precision < 0)
+ precision = 0;
+ }
+
+ /* get the conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
+ qualifier = *fmt;
+ ++fmt;
+ }
+
+ /* default base */
+ base = 10;
+
+ switch (*fmt) {
+ case 'c':
+ if (!(flags & LEFT))
+ while (--field_width > 0)
+ *str++ = ' ';
+ *str++ = (unsigned char) va_arg(args, int);
+ while (--field_width > 0)
+ *str++ = ' ';
+ continue;
+
+ case 's':
+ s = va_arg(args, char *);
+ if (!s)
+ s = "";
+
+ len = strnlen(s, precision);
+
+ if (!(flags & LEFT))
+ while (len < field_width--)
+ *str++ = ' ';
+ for (i = 0; i < len; ++i)
+ *str++ = *s++;
+ while (len < field_width--)
+ *str++ = ' ';
+ continue;
+
+ case 'p':
+ if (field_width == -1) {
+ field_width = 2*sizeof(void *);
+ flags |= ZEROPAD;
+ }
+ str = number(str,
+ (unsigned long) va_arg(args, void *), 16,
+ field_width, precision, flags);
+ continue;
+
+
+ case 'n':
+ if (qualifier == 'l') {
+ long * ip = va_arg(args, long *);
+ *ip = (str - buf);
+ } else if (qualifier == 'Z') {
+ size_t * ip = va_arg(args, size_t *);
+ *ip = (str - buf);
+ } else {
+ int * ip = va_arg(args, int *);
+ *ip = (str - buf);
+ }
+ continue;
+
+ case '%':
+ *str++ = '%';
+ continue;
+
+ /* integer number formats - set up the flags and "break" */
+ case 'o':
+ base = 8;
+ break;
+
+ case 'X':
+ flags |= LARGE;
+ case 'x':
+ base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+ flags |= SIGN;
+ case 'u':
+ break;
+
+ default:
+ *str++ = '%';
+ if (*fmt)
+ *str++ = *fmt;
+ else
+ --fmt;
+ continue;
+ }
+ if (qualifier == 'L')
+ num = va_arg(args, long long);
+ else if (qualifier == 'l') {
+ num = va_arg(args, unsigned long);
+ if (flags & SIGN)
+ num = (signed long) num;
+ } else if (qualifier == 'Z') {
+ num = va_arg(args, size_t);
+ } else if (qualifier == 'h') {
+ num = (unsigned short) va_arg(args, int);
+ if (flags & SIGN)
+ num = (signed short) num;
+ } else {
+ num = va_arg(args, unsigned int);
+ if (flags & SIGN)
+ num = (signed int) num;
+ }
+ str = number(str, num, base, field_width, precision, flags);
+ }
+ *str = '\0';
+ return str-buf;
+}
+
+int sprintf(char * buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsprintf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+
+static char sprint_buf[1024];
+
+void
+printk(char *fmt, ...)
+{
+ va_list args;
+ int n;
+
+ va_start(args, fmt);
+ n = vsprintf(sprint_buf, fmt, args);
+ va_end(args);
+ write(stdout, sprint_buf, n);
+}
+
+int
+printf(char *fmt, ...)
+{
+ va_list args;
+ int n;
+
+ va_start(args, fmt);
+ n = vsprintf(sprint_buf, fmt, args);
+ va_end(args);
+ write(stdout, sprint_buf, n);
+ return n;
+}
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/zImage.lds linuxppc64_2_4/arch/ppc64/boot/zImage.lds
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/zImage.lds Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/boot/zImage.lds Tue Sep 11 08:57:14 2001
@@ -0,0 +1,78 @@
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ . = ALIGN(4096);
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
+ .kstrtab : { *(.kstrtab) }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+ /* Read-write section, merged into data segment: */
+ . = ALIGN(4096);
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.got.plt) *(.got)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ . = ALIGN(4096);
+ _edata = .;
+ PROVIDE (edata = .);
+
+ .fixup : { *(.fixup) }
+
+ . = ALIGN(4096);
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ . = ALIGN(4096);
+ _end = . ;
+ PROVIDE (end = .);
+}
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/zlib.c linuxppc64_2_4/arch/ppc64/boot/zlib.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/zlib.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/boot/zlib.c Mon Jun 18 13:47:13 2001
@@ -0,0 +1,2170 @@
+/*
+ * This file is derived from various .h and .c files from the zlib-0.95
+ * distribution by Jean-loup Gailly and Mark Adler, with some additions
+ * by Paul Mackerras to aid in implementing Deflate compression and
+ * decompression for PPP packets. See zlib.h for conditions of
+ * distribution and use.
+ *
+ * Changes that have been made include:
+ * - changed functions not used outside this file to "local"
+ * - added minCompression parameter to deflateInit2
+ * - added Z_PACKET_FLUSH (see zlib.h for details)
+ * - added inflateIncomp
+ *
+ Copyright (C) 1995 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ gzip@prep.ai.mit.edu madler@alumni.caltech.edu
+
+ *
+ *
+ */
+
+/*+++++*/
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* From: zutil.h,v 1.9 1995/05/03 17:27:12 jloup Exp */
+
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+#define FAR
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+extern char *z_errmsg[]; /* indexed by 1-zlib_error */
+
+#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err)
+/* To be used only when the state is known to be valid */
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+ /* common constants */
+
+#define DEFLATED 8
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+ /* functions */
+
+#include
+#define zmemcpy memcpy
+#define zmemzero(dest, len) memset(dest, 0, len)
+
+/* Diagnostic functions */
+#ifdef DEBUG_ZLIB
+# include
+# ifndef verbose
+# define verbose 0
+# endif
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) fprintf x
+# define Tracev(x) {if (verbose) fprintf x ;}
+# define Tracevv(x) {if (verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+
+typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len));
+
+/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */
+/* void zcfree OF((voidpf opaque, voidpf ptr)); */
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr, size) \
+ (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size))
+#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);}
+
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/*+++++*/
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+local inflate_blocks_statef * inflate_blocks_new OF((
+ z_stream *z,
+ check_func c, /* check function */
+ uInt w)); /* window size */
+
+local int inflate_blocks OF((
+ inflate_blocks_statef *,
+ z_stream *,
+ int)); /* initial return code */
+
+local void inflate_blocks_reset OF((
+ inflate_blocks_statef *,
+ z_stream *,
+ uLongf *)); /* check value on output */
+
+local int inflate_blocks_free OF((
+ inflate_blocks_statef *,
+ z_stream *,
+ uLongf *)); /* check value on output */
+
+local int inflate_addhistory OF((
+ inflate_blocks_statef *,
+ z_stream *));
+
+local int inflate_packet_flush OF((
+ inflate_blocks_statef *));
+
+/*+++++*/
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+ that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+typedef struct inflate_huft_s FAR inflate_huft;
+
+struct inflate_huft_s {
+ union {
+ struct {
+ Byte Exop; /* number of extra bits or operation */
+ Byte Bits; /* number of bits in this code or subcode */
+ } what;
+ uInt Nalloc; /* number of these allocated here */
+ Bytef *pad; /* pad structure to a power of 2 (4 bytes for */
+ } word; /* 16-bit, 8 bytes for 32-bit machines) */
+ union {
+ uInt Base; /* literal, length base, or distance base */
+ inflate_huft *Next; /* pointer to next level of table */
+ } more;
+};
+
+#ifdef DEBUG_ZLIB
+ local uInt inflate_hufts;
+#endif
+
+local int inflate_trees_bits OF((
+ uIntf *, /* 19 code lengths */
+ uIntf *, /* bits tree desired/actual depth */
+ inflate_huft * FAR *, /* bits tree result */
+ z_stream *)); /* for zalloc, zfree functions */
+
+local int inflate_trees_dynamic OF((
+ uInt, /* number of literal/length codes */
+ uInt, /* number of distance codes */
+ uIntf *, /* that many (total) code lengths */
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ inflate_huft * FAR *, /* literal/length tree result */
+ inflate_huft * FAR *, /* distance tree result */
+ z_stream *)); /* for zalloc, zfree functions */
+
+local int inflate_trees_fixed OF((
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ inflate_huft * FAR *, /* literal/length tree result */
+ inflate_huft * FAR *)); /* distance tree result */
+
+local int inflate_trees_free OF((
+ inflate_huft *, /* tables to free */
+ z_stream *)); /* for zfree function */
+
+
+/*+++++*/
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+local inflate_codes_statef *inflate_codes_new OF((
+ uInt, uInt,
+ inflate_huft *, inflate_huft *,
+ z_stream *));
+
+local int inflate_codes OF((
+ inflate_blocks_statef *,
+ z_stream *,
+ int));
+
+local void inflate_codes_free OF((
+ inflate_codes_statef *,
+ z_stream *));
+
+
+/*+++++*/
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* inflate private state */
+struct internal_state {
+
+ /* mode */
+ enum {
+ METHOD, /* waiting for method byte */
+ FLAG, /* waiting for flag byte */
+ BLOCKS, /* decompressing blocks */
+ CHECK4, /* four check bytes to go */
+ CHECK3, /* three check bytes to go */
+ CHECK2, /* two check bytes to go */
+ CHECK1, /* one check byte to go */
+ DONE, /* finished check, done */
+ BAD} /* got an error--stay here */
+ mode; /* current inflate mode */
+
+ /* mode dependent information */
+ union {
+ uInt method; /* if FLAGS, method byte */
+ struct {
+ uLong was; /* computed check value */
+ uLong need; /* stream check value */
+ } check; /* if CHECK, check values to compare */
+ uInt marker; /* if BAD, inflateSync's marker bytes count */
+ } sub; /* submode */
+
+ /* mode independent information */
+ int nowrap; /* flag for no wrapper */
+ uInt wbits; /* log2(window size) (8..15, defaults to 15) */
+ inflate_blocks_statef
+ *blocks; /* current inflate_blocks state */
+
+};
+
+
+int inflateReset(z)
+z_stream *z;
+{
+ uLong c;
+
+ if (z == Z_NULL || z->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ z->total_in = z->total_out = 0;
+ z->msg = Z_NULL;
+ z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+ inflate_blocks_reset(z->state->blocks, z, &c);
+ Trace((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+
+int inflateEnd(z)
+z_stream *z;
+{
+ uLong c;
+
+ if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+ return Z_STREAM_ERROR;
+ if (z->state->blocks != Z_NULL)
+ inflate_blocks_free(z->state->blocks, z, &c);
+ ZFREE(z, z->state, sizeof(struct internal_state));
+ z->state = Z_NULL;
+ Trace((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+
+int inflateInit2(z, w)
+z_stream *z;
+int w;
+{
+ /* initialize state */
+ if (z == Z_NULL)
+ return Z_STREAM_ERROR;
+/* if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */
+/* if (z->zfree == Z_NULL) z->zfree = zcfree; */
+ if ((z->state = (struct internal_state FAR *)
+ ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+ return Z_MEM_ERROR;
+ z->state->blocks = Z_NULL;
+
+ /* handle undocumented nowrap option (no zlib header or check) */
+ z->state->nowrap = 0;
+ if (w < 0)
+ {
+ w = - w;
+ z->state->nowrap = 1;
+ }
+
+ /* set window size */
+ if (w < 8 || w > 15)
+ {
+ inflateEnd(z);
+ return Z_STREAM_ERROR;
+ }
+ z->state->wbits = (uInt)w;
+
+ /* create inflate_blocks state */
+ if ((z->state->blocks =
+ inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w))
+ == Z_NULL)
+ {
+ inflateEnd(z);
+ return Z_MEM_ERROR;
+ }
+ Trace((stderr, "inflate: allocated\n"));
+
+ /* reset state */
+ inflateReset(z);
+ return Z_OK;
+}
+
+
+int inflateInit(z)
+z_stream *z;
+{
+ return inflateInit2(z, DEF_WBITS);
+}
+
+
+#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;}
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+int inflate(z, f)
+z_stream *z;
+int f;
+{
+ int r;
+ uInt b;
+
+ if (z == Z_NULL || z->next_in == Z_NULL)
+ return Z_STREAM_ERROR;
+ r = Z_BUF_ERROR;
+ while (1) switch (z->state->mode)
+ {
+ case METHOD:
+ NEEDBYTE
+ if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED)
+ {
+ z->state->mode = BAD;
+ z->msg = "unknown compression method";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+ {
+ z->state->mode = BAD;
+ z->msg = "invalid window size";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ z->state->mode = FLAG;
+ case FLAG:
+ NEEDBYTE
+ if ((b = NEXTBYTE) & 0x20)
+ {
+ z->state->mode = BAD;
+ z->msg = "invalid reserved bit";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ if (((z->state->sub.method << 8) + b) % 31)
+ {
+ z->state->mode = BAD;
+ z->msg = "incorrect header check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ Trace((stderr, "inflate: zlib header ok\n"));
+ z->state->mode = BLOCKS;
+ case BLOCKS:
+ r = inflate_blocks(z->state->blocks, z, r);
+ if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
+ r = inflate_packet_flush(z->state->blocks);
+ if (r == Z_DATA_ERROR)
+ {
+ z->state->mode = BAD;
+ z->state->sub.marker = 0; /* can try inflateSync */
+ break;
+ }
+ if (r != Z_STREAM_END)
+ return r;
+ r = Z_OK;
+ inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+ if (z->state->nowrap)
+ {
+ z->state->mode = DONE;
+ break;
+ }
+ z->state->mode = CHECK4;
+ case CHECK4:
+ NEEDBYTE
+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+ z->state->mode = CHECK3;
+ case CHECK3:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+ z->state->mode = CHECK2;
+ case CHECK2:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+ z->state->mode = CHECK1;
+ case CHECK1:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE;
+
+ if (z->state->sub.check.was != z->state->sub.check.need)
+ {
+ z->state->mode = BAD;
+ z->msg = "incorrect data check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ Trace((stderr, "inflate: zlib check ok\n"));
+ z->state->mode = DONE;
+ case DONE:
+ return Z_STREAM_END;
+ case BAD:
+ return Z_DATA_ERROR;
+ default:
+ return Z_STREAM_ERROR;
+ }
+
+ empty:
+ if (f != Z_PACKET_FLUSH)
+ return r;
+ z->state->mode = BAD;
+ z->state->sub.marker = 0; /* can try inflateSync */
+ return Z_DATA_ERROR;
+}
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output. The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS). On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+
+int inflateIncomp(z)
+z_stream *z;
+{
+ if (z->state->mode != BLOCKS)
+ return Z_DATA_ERROR;
+ return inflate_addhistory(z->state->blocks, z);
+}
+
+
+int inflateSync(z)
+z_stream *z;
+{
+ uInt n; /* number of bytes to look at */
+ Bytef *p; /* pointer to bytes */
+ uInt m; /* number of marker bytes found in a row */
+ uLong r, w; /* temporaries to save total_in and total_out */
+
+ /* set up */
+ if (z == Z_NULL || z->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ if (z->state->mode != BAD)
+ {
+ z->state->mode = BAD;
+ z->state->sub.marker = 0;
+ }
+ if ((n = z->avail_in) == 0)
+ return Z_BUF_ERROR;
+ p = z->next_in;
+ m = z->state->sub.marker;
+
+ /* search */
+ while (n && m < 4)
+ {
+ if (*p == (Byte)(m < 2 ? 0 : 0xff))
+ m++;
+ else if (*p)
+ m = 0;
+ else
+ m = 4 - m;
+ p++, n--;
+ }
+
+ /* restore */
+ z->total_in += p - z->next_in;
+ z->next_in = p;
+ z->avail_in = n;
+ z->state->sub.marker = m;
+
+ /* return no joy or set up to restart on a new block */
+ if (m != 4)
+ return Z_DATA_ERROR;
+ r = z->total_in; w = z->total_out;
+ inflateReset(z);
+ z->total_in = r; z->total_out = w;
+ z->state->mode = BLOCKS;
+ return Z_OK;
+}
+
+#undef NEEDBYTE
+#undef NEXTBYTE
+
+/*+++++*/
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+ /* mode */
+ enum {
+ TYPE, /* get type bits (3, including end bit) */
+ LENS, /* get lengths for stored */
+ STORED, /* processing stored block */
+ TABLE, /* get table lengths */
+ BTREE, /* get bit lengths tree for a dynamic block */
+ DTREE, /* get length, distance trees for a dynamic block */
+ CODES, /* processing fixed or dynamic block */
+ DRY, /* output remaining window bytes */
+ DONEB, /* finished last block, done */
+ BADB} /* got a data error--stuck here */
+ mode; /* current inflate_block mode */
+
+ /* mode dependent information */
+ union {
+ uInt left; /* if STORED, bytes left to copy */
+ struct {
+ uInt table; /* table lengths (14 bits) */
+ uInt index; /* index into blens (or border) */
+ uIntf *blens; /* bit lengths of codes */
+ uInt bb; /* bit length tree depth */
+ inflate_huft *tb; /* bit length decoding tree */
+ int nblens; /* # elements allocated at blens */
+ } trees; /* if DTREE, decoding info for trees */
+ struct {
+ inflate_huft *tl, *td; /* trees to free */
+ inflate_codes_statef
+ *codes;
+ } decode; /* if CODES, current state */
+ } sub; /* submode */
+ uInt last; /* true if this block is the last block */
+
+ /* mode independent information */
+ uInt bitk; /* bits in bit buffer */
+ uLong bitb; /* bit buffer */
+ Bytef *window; /* sliding window */
+ Bytef *end; /* one byte after sliding window */
+ Bytef *read; /* window read pointer */
+ Bytef *write; /* window write pointer */
+ check_func checkfn; /* check function */
+ uLong check; /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/* update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/* get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);}
+/* output bytes */
+#define WAVAIL (qread?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/* load local pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/*
+ * The IBM 150 firmware munges the data right after _etext[]. This
+ * protects it. -- Cort
+ */
+local uInt protect_mask[] = {0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0};
+/* And'ing with mask[n] masks the lower n bits */
+local uInt inflate_mask[] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+/* copy as much as possible from the sliding window to the output area */
+local int inflate_flush OF((
+ inflate_blocks_statef *,
+ z_stream *,
+ int));
+
+/*+++++*/
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+local int inflate_fast OF((
+ uInt,
+ uInt,
+ inflate_huft *,
+ inflate_huft *,
+ inflate_blocks_statef *,
+ z_stream *));
+
+
+/*+++++*/
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local uInt border[] = { /* Order of the bit length code lengths */
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/*
+ Notes beyond the 1.93a appnote.txt:
+
+ 1. Distance pointers never point before the beginning of the output
+ stream.
+ 2. Distance pointers can point back across blocks, up to 32k away.
+ 3. There is an implied maximum of 7 bits for the bit length table and
+ 15 bits for the actual data.
+ 4. If only one code exists, then it is encoded using one bit. (Zero
+ would be more efficient, but perhaps a little confusing.) If two
+ codes exist, they are coded using one bit each (0 and 1).
+ 5. There is no way of sending zero distance codes--a dummy must be
+ sent if there are none. (History: a pre 2.0 version of PKZIP would
+ store blocks with no distance codes, but this was discovered to be
+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
+ zero distance codes, which is sent as one code of zero bits in
+ length.
+ 6. There are up to 286 literal/length codes. Code 256 represents the
+ end-of-block. Note however that the static length tree defines
+ 288 codes just to fill out the Huffman codes. Codes 286 and 287
+ cannot be used though, since there is no length base or extra bits
+ defined for them. Similarily, there are up to 30 distance codes.
+ However, static trees define 32 codes (all 5 bits) to fill out the
+ Huffman codes, but the last two had better not show up in the data.
+ 7. Unzip can check dynamic Huffman blocks for complete code sets.
+ The exception is that a single code would not be complete (see #4).
+ 8. The five bits following the block type is really the number of
+ literal codes sent minus 257.
+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+ (1+6+6). Therefore, to output three times the length, you output
+ three codes (1+1+1), whereas to output four times the same length,
+ you only need two codes (1+3). Hmm.
+ 10. In the tree reconstruction algorithm, Code = Code + Increment
+ only if BitLength(i) is not zero. (Pretty obvious.)
+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
+ 12. Note: length code 284 can represent 227-258, but length code 285
+ really is 258. The last length deserves its own, short code
+ since it gets used a lot in very redundant files. The length
+ 258 is special since 258 - 3 (the min match length) is 255.
+ 13. The literal/length and distance code bit lengths are read as a
+ single stream of lengths. It is possible (and advantageous) for
+ a repeat code (16, 17, or 18) to go across the boundary between
+ the two sets of lengths.
+ */
+
+
+local void inflate_blocks_reset(s, z, c)
+inflate_blocks_statef *s;
+z_stream *z;
+uLongf *c;
+{
+ if (s->checkfn != Z_NULL)
+ *c = s->check;
+ if (s->mode == BTREE || s->mode == DTREE)
+ ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
+ if (s->mode == CODES)
+ {
+ inflate_codes_free(s->sub.decode.codes, z);
+ inflate_trees_free(s->sub.decode.td, z);
+ inflate_trees_free(s->sub.decode.tl, z);
+ }
+ s->mode = TYPE;
+ s->bitk = 0;
+ s->bitb = 0;
+ s->read = s->write = s->window;
+ if (s->checkfn != Z_NULL)
+ s->check = (*s->checkfn)(0L, Z_NULL, 0);
+ Trace((stderr, "inflate: blocks reset\n"));
+}
+
+
+local inflate_blocks_statef *inflate_blocks_new(z, c, w)
+z_stream *z;
+check_func c;
+uInt w;
+{
+ inflate_blocks_statef *s;
+
+ if ((s = (inflate_blocks_statef *)ZALLOC
+ (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+ return s;
+ if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+ {
+ ZFREE(z, s, sizeof(struct inflate_blocks_state));
+ return Z_NULL;
+ }
+ s->end = s->window + w;
+ s->checkfn = c;
+ s->mode = TYPE;
+ Trace((stderr, "inflate: blocks allocated\n"));
+ inflate_blocks_reset(s, z, &s->check);
+ return s;
+}
+
+
+local int inflate_blocks(s, z, r)
+inflate_blocks_statef *s;
+z_stream *z;
+int r;
+{
+ uInt t; /* temporary storage */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input based on current state */
+ while (1) switch (s->mode)
+ {
+ case TYPE:
+ NEEDBITS(3)
+ t = (uInt)b & 7;
+ s->last = t & 1;
+ switch (t >> 1)
+ {
+ case 0: /* stored */
+ Trace((stderr, "inflate: stored block%s\n",
+ s->last ? " (last)" : ""));
+ DUMPBITS(3)
+ t = k & 7; /* go to byte boundary */
+ DUMPBITS(t)
+ s->mode = LENS; /* get length of stored block */
+ break;
+ case 1: /* fixed */
+ Trace((stderr, "inflate: fixed codes block%s\n",
+ s->last ? " (last)" : ""));
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+
+ inflate_trees_fixed(&bl, &bd, &tl, &td);
+ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+ if (s->sub.decode.codes == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ s->sub.decode.tl = Z_NULL; /* don't try to free these */
+ s->sub.decode.td = Z_NULL;
+ }
+ DUMPBITS(3)
+ s->mode = CODES;
+ break;
+ case 2: /* dynamic */
+ Trace((stderr, "inflate: dynamic codes block%s\n",
+ s->last ? " (last)" : ""));
+ DUMPBITS(3)
+ s->mode = TABLE;
+ break;
+ case 3: /* illegal */
+ DUMPBITS(3)
+ s->mode = BADB;
+ z->msg = "invalid block type";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ break;
+ case LENS:
+ NEEDBITS(32)
+ if (((~b) >> 16) != (b & 0xffff))
+ {
+ s->mode = BADB;
+ z->msg = "invalid stored block lengths";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ s->sub.left = (uInt)b & 0xffff;
+ b = k = 0; /* dump bits */
+ Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
+ s->mode = s->sub.left ? STORED : TYPE;
+ break;
+ case STORED:
+ if (n == 0)
+ LEAVE
+ NEEDOUT
+ t = s->sub.left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ zmemcpy(q, p, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((s->sub.left -= t) != 0)
+ break;
+ Tracev((stderr, "inflate: stored end, %lu total out\n",
+ z->total_out + (q >= s->read ? q - s->read :
+ (s->end - s->read) + (q - s->window))));
+ s->mode = s->last ? DRY : TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14)
+ s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ s->mode = BADB;
+ z->msg = "too many length or distance symbols";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+#endif
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (t < 19)
+ t = 19;
+ if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ s->sub.trees.nblens = t;
+ DUMPBITS(14)
+ s->sub.trees.index = 0;
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ s->mode = BTREE;
+ case BTREE:
+ while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+ {
+ NEEDBITS(3)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+ DUMPBITS(3)
+ }
+ while (s->sub.trees.index < 19)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+ s->sub.trees.bb = 7;
+ t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+ &s->sub.trees.tb, z);
+ if (t != Z_OK)
+ {
+ r = t;
+ if (r == Z_DATA_ERROR)
+ s->mode = BADB;
+ LEAVE
+ }
+ s->sub.trees.index = 0;
+ Tracev((stderr, "inflate: bits tree ok\n"));
+ s->mode = DTREE;
+ case DTREE:
+ while (t = s->sub.trees.table,
+ s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+ {
+ inflate_huft *h;
+ uInt i, j, c;
+
+ t = s->sub.trees.bb;
+ NEEDBITS(t)
+ h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+ t = h->word.what.Bits;
+ c = h->more.Base;
+ if (c < 16)
+ {
+ DUMPBITS(t)
+ s->sub.trees.blens[s->sub.trees.index++] = c;
+ }
+ else /* c == 16..18 */
+ {
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+ NEEDBITS(t + i)
+ DUMPBITS(t)
+ j += (uInt)b & inflate_mask[i];
+ DUMPBITS(i)
+ i = s->sub.trees.index;
+ t = s->sub.trees.table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ s->mode = BADB;
+ z->msg = "invalid bit length repeat";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+ do {
+ s->sub.trees.blens[i++] = c;
+ } while (--j);
+ s->sub.trees.index = i;
+ }
+ }
+ inflate_trees_free(s->sub.trees.tb, z);
+ s->sub.trees.tb = Z_NULL;
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+ inflate_codes_statef *c;
+
+ bl = 9; /* must be <= 9 for lookahead assumptions */
+ bd = 6; /* must be <= 9 for lookahead assumptions */
+ t = s->sub.trees.table;
+ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+ s->sub.trees.blens, &bl, &bd, &tl, &td, z);
+ if (t != Z_OK)
+ {
+ if (t == (uInt)Z_DATA_ERROR)
+ s->mode = BADB;
+ r = t;
+ LEAVE
+ }
+ Tracev((stderr, "inflate: trees ok\n"));
+ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+ {
+ inflate_trees_free(td, z);
+ inflate_trees_free(tl, z);
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
+ s->sub.decode.codes = c;
+ s->sub.decode.tl = tl;
+ s->sub.decode.td = td;
+ }
+ s->mode = CODES;
+ case CODES:
+ UPDATE
+ if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+ return inflate_flush(s, z, r);
+ r = Z_OK;
+ inflate_codes_free(s->sub.decode.codes, z);
+ inflate_trees_free(s->sub.decode.td, z);
+ inflate_trees_free(s->sub.decode.tl, z);
+ LOAD
+ Tracev((stderr, "inflate: codes end, %lu total out\n",
+ z->total_out + (q >= s->read ? q - s->read :
+ (s->end - s->read) + (q - s->window))));
+ if (!s->last)
+ {
+ s->mode = TYPE;
+ break;
+ }
+ if (k > 7) /* return unused byte, if any */
+ {
+ Assert(k < 16, "inflate_codes grabbed too many bytes")
+ k -= 8;
+ n++;
+ p--; /* can always return one */
+ }
+ s->mode = DRY;
+ case DRY:
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ s->mode = DONEB;
+ case DONEB:
+ r = Z_STREAM_END;
+ LEAVE
+ case BADB:
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+}
+
+
+local int inflate_blocks_free(s, z, c)
+inflate_blocks_statef *s;
+z_stream *z;
+uLongf *c;
+{
+ inflate_blocks_reset(s, z, c);
+ ZFREE(z, s->window, s->end - s->window);
+ ZFREE(z, s, sizeof(struct inflate_blocks_state));
+ Trace((stderr, "inflate: blocks freed\n"));
+ return Z_OK;
+}
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output. The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS). On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+local int inflate_addhistory(s, z)
+inflate_blocks_statef *s;
+z_stream *z;
+{
+ uLong b; /* bit buffer */ /* NOT USED HERE */
+ uInt k; /* bits in bit buffer */ /* NOT USED HERE */
+ uInt t; /* temporary storage */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+
+ if (s->read != s->write)
+ return Z_STREAM_ERROR;
+ if (s->mode != TYPE)
+ return Z_DATA_ERROR;
+
+ /* we're ready to rock */
+ LOAD
+ /* while there is input ready, copy to output buffer, moving
+ * pointers as needed.
+ */
+ while (n) {
+ t = n; /* how many to do */
+ /* is there room until end of buffer? */
+ if (t > m) t = m;
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ s->check = (*s->checkfn)(s->check, q, t);
+ zmemcpy(q, p, t);
+ q += t;
+ p += t;
+ n -= t;
+ z->total_out += t;
+ s->read = q; /* drag read pointer forward */
+/* WRAP */ /* expand WRAP macro by hand to handle s->read */
+ if (q == s->end) {
+ s->read = q = s->window;
+ m = WAVAIL;
+ }
+ }
+ UPDATE
+ return Z_OK;
+}
+
+
+/*
+ * At the end of a Deflate-compressed PPP packet, we expect to have seen
+ * a `stored' block type value but not the (zero) length bytes.
+ */
+local int inflate_packet_flush(s)
+ inflate_blocks_statef *s;
+{
+ if (s->mode != LENS)
+ return Z_DATA_ERROR;
+ s->mode = TYPE;
+ return Z_OK;
+}
+
+
+/*+++++*/
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+ uIntf *, /* code lengths in bits */
+ uInt, /* number of codes */
+ uInt, /* number of "simple" codes */
+ uIntf *, /* list of base values for non-simple codes */
+ uIntf *, /* list of extra bits for non-simple codes */
+ inflate_huft * FAR*,/* result: starting table */
+ uIntf *, /* maximum lookup bits (returns actual) */
+ z_stream *)); /* for zalloc function */
+
+local voidpf falloc OF((
+ voidpf, /* opaque pointer (not used) */
+ uInt, /* number of items */
+ uInt)); /* size of item */
+
+local void ffree OF((
+ voidpf q, /* opaque pointer (not used) */
+ voidpf p, /* what to free (not used) */
+ uInt n)); /* number of bytes (not used) */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ /* actually lengths - 2; also see note #13 above about 258 */
+local uInt cplext[] = { /* Extra bits for literal codes 257..285 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */
+local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577};
+local uInt cpdext[] = { /* Extra bits for distance codes */
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+/*
+ Huffman code decoding is performed using a multi-level table lookup.
+ The fastest way to decode is to simply build a lookup table whose
+ size is determined by the longest code. However, the time it takes
+ to build this table can also be a factor if the data being decoded
+ is not very long. The most common codes are necessarily the
+ shortest codes, so those codes dominate the decoding time, and hence
+ the speed. The idea is you can have a shorter table that decodes the
+ shorter, more probable codes, and then point to subsidiary tables for
+ the longer codes. The time it costs to decode the longer codes is
+ then traded against the time it takes to make longer tables.
+
+ This results of this trade are in the variables lbits and dbits
+ below. lbits is the number of bits the first level table for literal/
+ length codes can decode in one step, and dbits is the same thing for
+ the distance codes. Subsequent tables are also less than or equal to
+ those sizes. These values may be adjusted either when all of the
+ codes are shorter than that, in which case the longest code length in
+ bits is used, or when the shortest code is *longer* than the requested
+ table size, in which case the length of the shortest code in bits is
+ used.
+
+ There are two different values for the two tables, since they code a
+ different number of possibilities each. The literal/length table
+ codes 286 possible values, or in a flat code, a little over eight
+ bits. The distance table codes 30 possible values, or a little less
+ than five bits, flat. The optimum values for speed end up being
+ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+ The optimum values may differ though from machine to machine, and
+ possibly even between compilers. Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15 /* maximum bit length of any code */
+#define N_MAX 288 /* maximum number of codes in any set */
+
+#ifdef DEBUG_ZLIB
+ uInt inflate_hufts;
+#endif
+
+local int huft_build(b, n, s, d, e, t, m, zs)
+uIntf *b; /* code lengths in bits (all assumed <= BMAX) */
+uInt n; /* number of codes (assumed <= N_MAX) */
+uInt s; /* number of simple-valued codes (0..s-1) */
+uIntf *d; /* list of base values for non-simple codes */
+uIntf *e; /* list of extra bits for non-simple codes */
+inflate_huft * FAR *t; /* result: starting table */
+uIntf *m; /* maximum lookup bits, returns actual */
+z_stream *zs; /* for zalloc function */
+/* Given a list of code lengths and a maximum table size, make a set of
+ tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ if the given code set is incomplete (the tables are still built in this
+ case), Z_DATA_ERROR if the input is invalid (all zero length codes or an
+ over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */
+{
+
+ uInt a; /* counter for codes of length k */
+ uInt c[BMAX+1]; /* bit length count table */
+ uInt f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+ register uInt i; /* counter, current code */
+ register uInt j; /* counter */
+ register int k; /* number of bits in current code */
+ int l; /* bits per table (returned in m) */
+ register uIntf *p; /* pointer into c[], b[], or v[] */
+ inflate_huft *q; /* points to current table */
+ struct inflate_huft_s r; /* table entry for structure assignment */
+ inflate_huft *u[BMAX]; /* table stack */
+ uInt v[N_MAX]; /* values in order of bit length */
+ register int w; /* bits before this table == (l * h) */
+ uInt x[BMAX+1]; /* bit offsets, then code stack */
+ uIntf *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ uInt z; /* number of entries in current table */
+
+
+ /* Generate counts for each bit length */
+ p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+ C4 /* clear c[]--assume BMAX+1 is 16 */
+ p = b; i = n;
+ do {
+ c[*p++]++; /* assume all entries <= BMAX */
+ } while (--i);
+ if (c[0] == n) /* null input--all zero length codes */
+ {
+ *t = (inflate_huft *)Z_NULL;
+ *m = 0;
+ return Z_OK;
+ }
+
+
+ /* Find minimum and maximum length, bound *m by those */
+ l = *m;
+ for (j = 1; j <= BMAX; j++)
+ if (c[j])
+ break;
+ k = j; /* minimum code length */
+ if ((uInt)l < j)
+ l = j;
+ for (i = BMAX; i; i--)
+ if (c[i])
+ break;
+ g = i; /* maximum code length */
+ if ((uInt)l > i)
+ l = i;
+ *m = l;
+
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ if ((y -= c[j]) < 0)
+ return Z_DATA_ERROR;
+ if ((y -= c[i]) < 0)
+ return Z_DATA_ERROR;
+ c[i] += y;
+
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1; xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ *xp++ = (j += *p++);
+ }
+
+
+ /* Make a table of values in order of bit lengths */
+ p = b; i = 0;
+ do {
+ if ((j = *p++) != 0)
+ v[x[j]++] = i;
+ } while (++i < n);
+
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ h = -1; /* no tables yet--level -1 */
+ w = -l; /* bits decoded == (l * h) */
+ u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
+ q = (inflate_huft *)Z_NULL; /* ditto */
+ z = 0; /* ditto */
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a--)
+ {
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > w + l)
+ {
+ h++;
+ w += l; /* previous table always l bits */
+
+ /* compute minimum size table less than or equal to l bits */
+ z = (z = g - w) > (uInt)l ? l : z; /* table size upper limit */
+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+ { /* too few codes for k-w bit table */
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ if (j < z)
+ while (++j < z) /* try smaller tables up to z bits */
+ {
+ if ((f <<= 1) <= *++xp)
+ break; /* enough codes to use up j bits */
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+ z = 1 << j; /* table entries for j-bit table */
+
+ /* allocate and link in new table */
+ if ((q = (inflate_huft *)ZALLOC
+ (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
+ {
+ if (h)
+ inflate_trees_free(u[0], zs);
+ return Z_MEM_ERROR; /* not enough memory */
+ }
+ q->word.Nalloc = z + 1;
+#ifdef DEBUG_ZLIB
+ inflate_hufts += z + 1;
+#endif
+ *t = q + 1; /* link to list for huft_free() */
+ *(t = &(q->next)) = Z_NULL;
+ u[h] = ++q; /* table starts after link */
+
+ /* connect to last table, if there is one */
+ if (h)
+ {
+ x[h] = i; /* save pattern for backing up */
+ r.bits = (Byte)l; /* bits to dump before this table */
+ r.exop = (Byte)j; /* bits in this table */
+ r.next = q; /* pointer to this table */
+ j = i >> (w - l); /* (get around Turbo C bug) */
+ u[h-1][j] = r; /* connect to last table */
+ }
+ }
+
+ /* set up table entry in r */
+ r.bits = (Byte)(k - w);
+ if (p >= v + n)
+ r.exop = 128 + 64; /* out of values--invalid code */
+ else if (*p < s)
+ {
+ r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
+ r.base = *p++; /* simple code is just the value */
+ }
+ else
+ {
+ r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */
+ r.base = d[*p++ - s];
+ }
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ q[j] = r;
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1)
+ i ^= j;
+ i ^= j;
+
+ /* backup over finished tables */
+ while ((i & ((1 << w) - 1)) != x[h])
+ {
+ h--; /* don't need to update q */
+ w -= l;
+ }
+ }
+ }
+
+
+ /* Return Z_BUF_ERROR if we were given an incomplete table */
+ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+local int inflate_trees_bits(c, bb, tb, z)
+uIntf *c; /* 19 code lengths */
+uIntf *bb; /* bits tree desired/actual depth */
+inflate_huft * FAR *tb; /* bits tree result */
+z_stream *z; /* for zfree function */
+{
+ int r;
+
+ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
+ if (r == Z_DATA_ERROR)
+ z->msg = "oversubscribed dynamic bit lengths tree";
+ else if (r == Z_BUF_ERROR)
+ {
+ inflate_trees_free(*tb, z);
+ z->msg = "incomplete dynamic bit lengths tree";
+ r = Z_DATA_ERROR;
+ }
+ return r;
+}
+
+
+local int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z)
+uInt nl; /* number of literal/length codes */
+uInt nd; /* number of distance codes */
+uIntf *c; /* that many (total) code lengths */
+uIntf *bl; /* literal desired/actual bit depth */
+uIntf *bd; /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+z_stream *z; /* for zfree function */
+{
+ int r;
+
+ /* build literal/length tree */
+ if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK)
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = "oversubscribed literal/length tree";
+ else if (r == Z_BUF_ERROR)
+ {
+ inflate_trees_free(*tl, z);
+ z->msg = "incomplete literal/length tree";
+ r = Z_DATA_ERROR;
+ }
+ return r;
+ }
+
+ /* build distance tree */
+ if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK)
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = "oversubscribed literal/length tree";
+ else if (r == Z_BUF_ERROR) {
+#ifdef PKZIP_BUG_WORKAROUND
+ r = Z_OK;
+ }
+#else
+ inflate_trees_free(*td, z);
+ z->msg = "incomplete literal/length tree";
+ r = Z_DATA_ERROR;
+ }
+ inflate_trees_free(*tl, z);
+ return r;
+#endif
+ }
+
+ /* done */
+ return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+local int fixed_lock = 0;
+local int fixed_built = 0;
+#define FIXEDH 530 /* number of hufts used by fixed tables */
+local uInt fixed_left = FIXEDH;
+local inflate_huft fixed_mem[FIXEDH];
+local uInt fixed_bl;
+local uInt fixed_bd;
+local inflate_huft *fixed_tl;
+local inflate_huft *fixed_td;
+
+
+local voidpf falloc(q, n, s)
+voidpf q; /* opaque pointer (not used) */
+uInt n; /* number of items */
+uInt s; /* size of item */
+{
+ Assert(s == sizeof(inflate_huft) && n <= fixed_left,
+ "inflate_trees falloc overflow");
+ if (q) s++; /* to make some compilers happy */
+ fixed_left -= n;
+ return (voidpf)(fixed_mem + fixed_left);
+}
+
+
+local void ffree(q, p, n)
+voidpf q;
+voidpf p;
+uInt n;
+{
+ Assert(0, "inflate_trees ffree called!");
+ if (q) q = p; /* to make some compilers happy */
+}
+
+
+local int inflate_trees_fixed(bl, bd, tl, td)
+uIntf *bl; /* literal desired/actual bit depth */
+uIntf *bd; /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+{
+ /* build fixed tables if not built already--lock out other instances */
+ while (++fixed_lock > 1)
+ fixed_lock--;
+ if (!fixed_built)
+ {
+ int k; /* temporary variable */
+ unsigned c[288]; /* length list for huft_build */
+ z_stream z; /* for falloc function */
+
+ /* set up fake z_stream for memory routines */
+ z.zalloc = falloc;
+ z.zfree = ffree;
+ z.opaque = Z_NULL;
+
+ /* literal table */
+ for (k = 0; k < 144; k++)
+ c[k] = 8;
+ for (; k < 256; k++)
+ c[k] = 9;
+ for (; k < 280; k++)
+ c[k] = 7;
+ for (; k < 288; k++)
+ c[k] = 8;
+ fixed_bl = 7;
+ huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
+
+ /* distance table */
+ for (k = 0; k < 30; k++)
+ c[k] = 5;
+ fixed_bd = 5;
+ huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
+
+ /* done */
+ fixed_built = 1;
+ }
+ fixed_lock--;
+ *bl = fixed_bl;
+ *bd = fixed_bd;
+ *tl = fixed_tl;
+ *td = fixed_td;
+ return Z_OK;
+}
+
+
+local int inflate_trees_free(t, z)
+inflate_huft *t; /* table to free */
+z_stream *z; /* for zfree function */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+ list of the tables it made, with the links in a dummy first entry of
+ each table. */
+{
+ register inflate_huft *p, *q;
+
+ /* Go through linked list, freeing from the malloced (t[-1]) address. */
+ p = t;
+ while (p != Z_NULL)
+ {
+ q = (--p)->next;
+ ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft));
+ p = q;
+ }
+ return Z_OK;
+}
+
+/*+++++*/
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+ /* mode */
+ enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ START, /* x: set up for LEN */
+ LEN, /* i: get length/literal/eob next */
+ LENEXT, /* i: getting length extra (have base) */
+ DIST, /* i: get distance next */
+ DISTEXT, /* i: getting distance extra */
+ COPY, /* o: copying bytes in window, waiting for space */
+ LIT, /* o: got literal, waiting for output space */
+ WASH, /* o: got eob, possibly still output waiting */
+ END, /* x: got eob and all data flushed */
+ BADCODE} /* x: got error */
+ mode; /* current inflate_codes mode */
+
+ /* mode dependent information */
+ uInt len;
+ union {
+ struct {
+ inflate_huft *tree; /* pointer into tree */
+ uInt need; /* bits needed */
+ } code; /* if LEN or DIST, where in tree */
+ uInt lit; /* if LIT, literal */
+ struct {
+ uInt get; /* bits to get for extra */
+ uInt dist; /* distance back to copy from */
+ } copy; /* if EXT or COPY, where and how much */
+ } sub; /* submode */
+
+ /* mode independent information */
+ Byte lbits; /* ltree bits decoded per branch */
+ Byte dbits; /* dtree bits decoder per branch */
+ inflate_huft *ltree; /* literal/length/eob tree */
+ inflate_huft *dtree; /* distance tree */
+
+};
+
+
+local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
+uInt bl, bd;
+inflate_huft *tl, *td;
+z_stream *z;
+{
+ inflate_codes_statef *c;
+
+ if ((c = (inflate_codes_statef *)
+ ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+ {
+ c->mode = START;
+ c->lbits = (Byte)bl;
+ c->dbits = (Byte)bd;
+ c->ltree = tl;
+ c->dtree = td;
+ Tracev((stderr, "inflate: codes new\n"));
+ }
+ return c;
+}
+
+
+local int inflate_codes(s, z, r)
+inflate_blocks_statef *s;
+z_stream *z;
+int r;
+{
+ uInt j; /* temporary storage */
+ inflate_huft *t; /* temporary pointer */
+ uInt e; /* extra bits or operation */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+ Bytef *f; /* pointer to copy strings from */
+ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input and output based on current state */
+ while (1) switch (c->mode)
+ { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ case START: /* x: set up for LEN */
+#ifndef SLOW
+ if (m >= 258 && n >= 10)
+ {
+ UPDATE
+ r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+ LOAD
+ if (r != Z_OK)
+ {
+ c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+ break;
+ }
+ }
+#endif /* !SLOW */
+ c->sub.code.need = c->lbits;
+ c->sub.code.tree = c->ltree;
+ c->mode = LEN;
+ case LEN: /* i: get length/literal/eob next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e == 0) /* literal */
+ {
+ c->sub.lit = t->base;
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", t->base));
+ c->mode = LIT;
+ break;
+ }
+ if (e & 16) /* length */
+ {
+ c->sub.copy.get = e & 15;
+ c->len = t->base;
+ c->mode = LENEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t->next;
+ break;
+ }
+ if (e & 32) /* end of block */
+ {
+ Tracevv((stderr, "inflate: end of block\n"));
+ c->mode = WASH;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = "invalid literal/length code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case LENEXT: /* i: getting length extra (have base) */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->len += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ c->sub.code.need = c->dbits;
+ c->sub.code.tree = c->dtree;
+ Tracevv((stderr, "inflate: length %u\n", c->len));
+ c->mode = DIST;
+ case DIST: /* i: get distance next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e & 16) /* distance */
+ {
+ c->sub.copy.get = e & 15;
+ c->sub.copy.dist = t->base;
+ c->mode = DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t->next;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = "invalid distance code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case DISTEXT: /* i: getting distance extra */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->sub.copy.dist += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
+ c->mode = COPY;
+ case COPY: /* o: copying bytes in window, waiting for space */
+#ifndef __TURBOC__ /* Turbo C bug for following expression */
+ f = (uInt)(q - s->window) < c->sub.copy.dist ?
+ s->end - (c->sub.copy.dist - (q - s->window)) :
+ q - c->sub.copy.dist;
+#else
+ f = q - c->sub.copy.dist;
+ if ((uInt)(q - s->window) < c->sub.copy.dist)
+ f = s->end - (c->sub.copy.dist - (q - s->window));
+#endif
+ while (c->len)
+ {
+ NEEDOUT
+ OUTBYTE(*f++)
+ if (f == s->end)
+ f = s->window;
+ c->len--;
+ }
+ c->mode = START;
+ break;
+ case LIT: /* o: got literal, waiting for output space */
+ NEEDOUT
+ OUTBYTE(c->sub.lit)
+ c->mode = START;
+ break;
+ case WASH: /* o: got eob, possibly more output */
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ c->mode = END;
+ case END:
+ r = Z_STREAM_END;
+ LEAVE
+ case BADCODE: /* x: got error */
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+}
+
+
+local void inflate_codes_free(c, z)
+inflate_codes_statef *c;
+z_stream *z;
+{
+ ZFREE(z, c, sizeof(struct inflate_codes_state));
+ Tracev((stderr, "inflate: codes free\n"));
+}
+
+/*+++++*/
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* copy as much as possible from the sliding window to the output area */
+local int inflate_flush(s, z, r)
+inflate_blocks_statef *s;
+z_stream *z;
+int r;
+{
+ uInt n;
+ Bytef *p, *q;
+
+ /* local copies of source and destination pointers */
+ p = z->next_out;
+ q = s->read;
+
+ /* compute number of bytes to copy as far as end of window */
+ n = (uInt)((q <= s->write ? s->write : s->end) - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy as far as end of window */
+ zmemcpy(p, q, n);
+ p += n;
+ q += n;
+
+ /* see if more to copy at beginning of window */
+ if (q == s->end)
+ {
+ /* wrap pointers */
+ q = s->window;
+ if (s->write == s->end)
+ s->write = s->window;
+
+ /* compute bytes to copy */
+ n = (uInt)(s->write - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy */
+ zmemcpy(p, q, n);
+ p += n;
+ q += n;
+ }
+
+ /* update pointers */
+ z->next_out = p;
+ s->read = q;
+
+ /* done */
+ return r;
+}
+
+
+/*+++++*/
+/* inffast.c -- process literals and length/distance pairs fast
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* macros for bit input with no checking and for returning unused bytes */
+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<>3);p-=c;k&=7;}
+
+/* Called with number of bytes left to write in window at least 258
+ (the maximum string length) and number of input bytes available
+ at least ten. The ten bytes are six bytes for the longest length/
+ distance pair plus four bytes for overloading the bit buffer. */
+
+local int inflate_fast(bl, bd, tl, td, s, z)
+uInt bl, bd;
+inflate_huft *tl, *td;
+inflate_blocks_statef *s;
+z_stream *z;
+{
+ inflate_huft *t; /* temporary pointer */
+ uInt e; /* extra bits or operation */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+ uInt ml; /* mask for literal/length tree */
+ uInt md; /* mask for distance tree */
+ uInt c; /* bytes to copy */
+ uInt d; /* distance back to copy from */
+ Bytef *r; /* copy source pointer */
+
+ /* load input, output, bit values */
+ LOAD
+
+ /* initialize masks */
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ /* do until not enough input or output space for fast loop */
+ do { /* assume called with m >= 258 && n >= 10 */
+ /* get literal/length code */
+ GRABBITS(20) /* max bits for literal/length code */
+ if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
+ {
+ DUMPBITS(t->bits)
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: * literal '%c'\n" :
+ "inflate: * literal 0x%02x\n", t->base));
+ *q++ = (Byte)t->base;
+ m--;
+ continue;
+ }
+ do {
+ DUMPBITS(t->bits)
+ if (e & 16)
+ {
+ /* get extra bits for length */
+ e &= 15;
+ c = t->base + ((uInt)b & inflate_mask[e]);
+ DUMPBITS(e)
+ Tracevv((stderr, "inflate: * length %u\n", c));
+
+ /* decode distance base of block to copy */
+ GRABBITS(15); /* max bits for distance code */
+ e = (t = td + ((uInt)b & md))->exop;
+ do {
+ DUMPBITS(t->bits)
+ if (e & 16)
+ {
+ /* get extra bits to add to distance base */
+ e &= 15;
+ GRABBITS(e) /* get extra bits (up to 13) */
+ d = t->base + ((uInt)b & inflate_mask[e]);
+ DUMPBITS(e)
+ Tracevv((stderr, "inflate: * distance %u\n", d));
+
+ /* do the copy */
+ m -= c;
+ if ((uInt)(q - s->window) >= d) /* offset before dest */
+ { /* just copy */
+ r = q - d;
+ *q++ = *r++; c--; /* minimum count is three, */
+ *q++ = *r++; c--; /* so unroll loop a little */
+ }
+ else /* else offset after destination */
+ {
+ e = d - (q - s->window); /* bytes from offset to end */
+ r = s->end - e; /* pointer to offset */
+ if (c > e) /* if source crosses, */
+ {
+ c -= e; /* copy to end of window */
+ do {
+ *q++ = *r++;
+ } while (--e);
+ r = s->window; /* copy rest from start of window */
+ }
+ }
+ do { /* copy all or what's left */
+ *q++ = *r++;
+ } while (--c);
+ break;
+ }
+ else if ((e & 64) == 0)
+ e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
+ else
+ {
+ z->msg = "invalid distance code";
+ UNGRAB
+ UPDATE
+ return Z_DATA_ERROR;
+ }
+ } while (1);
+ break;
+ }
+ if ((e & 64) == 0)
+ {
+ if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
+ {
+ DUMPBITS(t->bits)
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: * literal '%c'\n" :
+ "inflate: * literal 0x%02x\n", t->base));
+ *q++ = (Byte)t->base;
+ m--;
+ break;
+ }
+ }
+ else if (e & 32)
+ {
+ Tracevv((stderr, "inflate: * end of block\n"));
+ UNGRAB
+ UPDATE
+ return Z_STREAM_END;
+ }
+ else
+ {
+ z->msg = "invalid literal/length code";
+ UNGRAB
+ UPDATE
+ return Z_DATA_ERROR;
+ }
+ } while (1);
+ } while (m >= 258 && n >= 10);
+
+ /* not enough input or output--restore pointers and return */
+ UNGRAB
+ UPDATE
+ return Z_OK;
+}
+
+
+/*+++++*/
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */
+
+char *zlib_version = ZLIB_VERSION;
+
+char *z_errmsg[] = {
+"stream end", /* Z_STREAM_END 1 */
+"", /* Z_OK 0 */
+"file error", /* Z_ERRNO (-1) */
+"stream error", /* Z_STREAM_ERROR (-2) */
+"data error", /* Z_DATA_ERROR (-3) */
+"insufficient memory", /* Z_MEM_ERROR (-4) */
+"buffer error", /* Z_BUF_ERROR (-5) */
+""};
+
+
+/*+++++*/
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf) {s1 += *buf++; s2 += s1;}
+#define DO2(buf) DO1(buf); DO1(buf);
+#define DO4(buf) DO2(buf); DO2(buf);
+#define DO8(buf) DO4(buf); DO4(buf);
+#define DO16(buf) DO8(buf); DO8(buf);
+
+/* ========================================================================= */
+uLong adler32(adler, buf, len)
+ uLong adler;
+ Bytef *buf;
+ uInt len;
+{
+ unsigned long s1 = adler & 0xffff;
+ unsigned long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ if (buf == Z_NULL) return 1L;
+
+ while (len > 0) {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16) {
+ DO16(buf);
+ k -= 16;
+ }
+ if (k != 0) do {
+ DO1(buf);
+ } while (--k);
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+}
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/zlib.h linuxppc64_2_4/arch/ppc64/boot/zlib.h
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/boot/zlib.h Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/boot/zlib.h Mon Jun 18 13:47:13 2001
@@ -0,0 +1,432 @@
+/* */
+
+/*
+ * This file is derived from zlib.h and zconf.h from the zlib-0.95
+ * distribution by Jean-loup Gailly and Mark Adler, with some additions
+ * by Paul Mackerras to aid in implementing Deflate compression and
+ * decompression for PPP packets.
+ */
+
+/*
+ * ==FILEVERSION 960122==
+ *
+ * This marker is used by the Linux installation script to determine
+ * whether an up-to-date version of this file is already installed.
+ */
+
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 0.95, Aug 16th, 1995.
+
+ Copyright (C) 1995 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ gzip@prep.ai.mit.edu madler@alumni.caltech.edu
+ */
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+/* #include "zconf.h" */ /* included directly here */
+
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */
+
+/*
+ The library does not install any signal handler. It is recommended to
+ add at least a handler for SIGSEGV when decompressing; the library checks
+ the consistency of the input data whenever possible but may go nuts
+ for some forms of corrupted input.
+ */
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints
+ * at addresses which are not a multiple of their size.
+ * Under DOS, -DFAR=far or -DFAR=__far may be needed.
+ */
+
+#ifndef STDC
+# if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus)
+# define STDC
+# endif
+#endif
+
+#ifdef __MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */
+# include
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ 1 << (windowBits+2) + 1 << (memLevel+9)
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+typedef unsigned char Byte; /* 8 bits */
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+typedef Byte FAR Bytef;
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+/* end of original zconf.h */
+
+#define ZLIB_VERSION "0.95P"
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms may be added later and will have the same
+ stream interface.
+
+ For compression the application must provide the output buffer and
+ may optionally provide the input buffer for optimization. For decompression,
+ the application must provide the input buffer and may optionally provide
+ the output buffer for optimization.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address, uInt nbytes));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidp opaque; /* private data object passed to zalloc and zfree */
+
+ Byte data_type; /* best guess about the data type: ascii or binary */
+
+} z_stream;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1
+#define Z_FULL_FLUSH 2
+#define Z_SYNC_FLUSH 3 /* experimental: partial_flush + byte align */
+#define Z_FINISH 4
+#define Z_PACKET_FLUSH 5
+/* See deflate() below for the usage of these constants */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+/* error codes for the compression/decompression functions */
+
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_DEFAULT_STRATEGY 0
+
+#define Z_BINARY 0
+#define Z_ASCII 1
+#define Z_UNKNOWN 2
+/* Used to set the data_type field */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+extern char *zlib_version;
+/* The application can compare zlib_version and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ */
+
+ /* basic functions */
+
+extern int inflateInit OF((z_stream *strm));
+/*
+ Initializes the internal stream state for decompression. The fields
+ zalloc and zfree must be initialized before by the caller. If zalloc and
+ zfree are set to Z_NULL, inflateInit updates them to use default allocation
+ functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory. msg is set to null if there is no error message.
+ inflateInit does not perform any decompression: this will be done by
+ inflate().
+*/
+
+
+extern int inflate OF((z_stream *strm, int flush));
+/*
+ Performs one or both of the following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() always provides as much output as possible
+ (until there is no more input data or no more space in the output buffer).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate().
+
+ If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
+ inflate flushes as much output as possible to the output buffer. The
+ flushing behavior of inflate is not specified for values of the flush
+ parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
+ current implementation actually flushes as much output as possible
+ anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data
+ has been consumed, it is expecting to see the length field of a stored
+ block; if not, it returns Z_DATA_ERROR.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster routine
+ may be used for the single inflate() call.
+
+ inflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if the end of the
+ compressed data has been reached and all uncompressed output has been
+ produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if
+ the stream structure was inconsistent (for example if next_in or next_out
+ was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no
+ progress is possible or if there was not enough room in the output buffer
+ when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then
+ call inflateSync to look for a good compression block. */
+
+
+extern int inflateEnd OF((z_stream *strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* advanced functions */
+
+extern int inflateInit2 OF((z_stream *strm,
+ int windowBits));
+/*
+ This is another version of inflateInit with more compression options. The
+ fields next_out, zalloc and zfree must be initialized before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library (the value 16 will be allowed soon). The
+ default value is 15 if inflateInit is used instead. If a compressed stream
+ with a larger window size is given as input, inflate() will return with
+ the error code Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ If next_out is not null, the library will use this buffer for the history
+ buffer; the buffer must either be large enough to hold the entire output
+ data, or have at least 1<
+#include
+#include
+#include
+#include
+#include
+#include
+#ifndef _HVCALLSC_H
+#include
+#endif
+#include
+
+#ifndef _HVTYPES_H
+#include
+#endif
+
+
+/*=====================================================================
+ * Note that this call takes at MOST one page worth of data
+ */
+int HvCall_readLogBuffer(HvLpIndex lpIndex, void *buffer, u64 bufLen)
+{
+ struct HvLpBufferList *bufList;
+ u64 bytesLeft = bufLen;
+ u64 leftThisPage;
+ u64 curPtr = virt_to_absolute( (unsigned long) buffer );
+ u64 retVal;
+ int npages;
+ int i;
+
+ npages = 0;
+ while (bytesLeft) {
+ npages++;
+ leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr;
+
+ if (leftThisPage > bytesLeft)
+ bytesLeft = 0;
+ else
+ bytesLeft -= leftThisPage;
+
+ curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE;
+ }
+
+ if (npages == 0)
+ return 0;
+
+ bufList = (struct HvLpBufferList *)
+ kmalloc(npages * sizeof(struct HvLpBufferList), GFP_ATOMIC);
+ bytesLeft = bufLen;
+ curPtr = virt_to_absolute( (unsigned long) buffer );
+ for(i=0; i bytesLeft) {
+ bufList[i].len = bytesLeft;
+ bytesLeft = 0;
+ } else {
+ bufList[i].len = leftThisPage;
+ bytesLeft -= leftThisPage;
+ }
+
+ curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE;
+ }
+
+
+ retVal = HvCall3(HvCallBaseReadLogBuffer, lpIndex,
+ virt_to_absolute((unsigned long)bufList), bufLen);
+
+ kfree(bufList);
+
+ return (int)retVal;
+}
+
+/*=====================================================================
+ */
+void HvCall_writeLogBuffer(const void *buffer, u64 bufLen)
+{
+ struct HvLpBufferList bufList;
+ u64 bytesLeft = bufLen;
+ u64 leftThisPage;
+ u64 curPtr = virt_to_absolute( (unsigned long) buffer );
+
+ while (bytesLeft) {
+ bufList.addr = curPtr;
+
+ leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr;
+
+ if (leftThisPage > bytesLeft) {
+ bufList.len = bytesLeft;
+ bytesLeft = 0;
+ } else {
+ bufList.len = leftThisPage;
+ bytesLeft -= leftThisPage;
+ }
+
+ curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE;
+ }
+
+
+ HvCall2(HvCallBaseWriteLogBuffer,
+ virt_to_absolute((unsigned long)&bufList), bufLen);
+
+}
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/HvLpConfig.c linuxppc64_2_4/arch/ppc64/kernel/HvLpConfig.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/HvLpConfig.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/HvLpConfig.c Sat Oct 20 06:53:25 2001
@@ -0,0 +1,28 @@
+/*
+ * 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();
+}
+
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/HvLpEvent.c linuxppc64_2_4/arch/ppc64/kernel/HvLpEvent.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/HvLpEvent.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/HvLpEvent.c Fri May 4 17:13:58 2001
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2001 Mike Corrigan IBM Corp
+ *
+ * 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.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* Array of LpEvent handler functions */
+LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];
+unsigned lpEventHandlerPaths[HvLpEvent_Type_NumTypes];
+
+/* Register a handler for an LpEvent type */
+
+int HvLpEvent_registerHandler( HvLpEvent_Type eventType, LpEventHandler handler )
+{
+ int rc = 1;
+ if ( eventType < HvLpEvent_Type_NumTypes ) {
+ lpEventHandler[eventType] = handler;
+ rc = 0;
+ }
+ return rc;
+
+}
+
+int HvLpEvent_unregisterHandler( HvLpEvent_Type eventType )
+{
+ int rc = 1;
+ if ( eventType < HvLpEvent_Type_NumTypes ) {
+ if ( !lpEventHandlerPaths[eventType] ) {
+ lpEventHandler[eventType] = NULL;
+ rc = 0;
+ }
+ }
+ return rc;
+}
+
+/* (lpIndex is the partition index of the target partition.
+ * needed only for VirtualIo, VirtualLan and SessionMgr. Zero
+ * indicates to use our partition index - for the other types)
+ */
+int HvLpEvent_openPath( HvLpEvent_Type eventType, HvLpIndex lpIndex )
+{
+ int rc = 1;
+ if ( eventType < HvLpEvent_Type_NumTypes &&
+ lpEventHandler[eventType] ) {
+ if ( lpIndex == 0 )
+ lpIndex = itLpNaca.xLpIndex;
+ HvCallEvent_openLpEventPath( lpIndex, eventType );
+ ++lpEventHandlerPaths[eventType];
+ rc = 0;
+ }
+ return rc;
+}
+
+int HvLpEvent_closePath( HvLpEvent_Type eventType, HvLpIndex lpIndex )
+{
+ int rc = 1;
+ if ( eventType < HvLpEvent_Type_NumTypes &&
+ lpEventHandler[eventType] &&
+ lpEventHandlerPaths[eventType] ) {
+ if ( lpIndex == 0 )
+ lpIndex = itLpNaca.xLpIndex;
+ HvCallEvent_closeLpEventPath( lpIndex, eventType );
+ --lpEventHandlerPaths[eventType];
+ rc = 0;
+ }
+ return rc;
+}
+
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/ItLpQueue.c linuxppc64_2_4/arch/ppc64/kernel/ItLpQueue.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/ItLpQueue.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/ItLpQueue.c Tue Sep 18 14:27:22 2001
@@ -0,0 +1,168 @@
+/*
+ * ItLpQueue.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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static __inline__ int set_inUse( struct ItLpQueue * lpQueue )
+{
+ int t;
+ u32 * inUseP = &(lpQueue->xInUseWord);
+
+ __asm__ __volatile__("\n\
+1: lwarx %0,0,%2 \n\
+ cmpi 0,%0,0 \n\
+ li %0,0 \n\
+ bne- 2f \n\
+ addi %0,%0,1 \n\
+ stwcx. %0,0,%2 \n\
+ bne- 1b \n\
+2: eieio"
+ : "=&r" (t), "=m" (lpQueue->xInUseWord)
+ : "r" (inUseP), "m" (lpQueue->xInUseWord)
+ : "cc");
+
+ return t;
+}
+
+static __inline__ void clear_inUse( struct ItLpQueue * lpQueue )
+{
+ lpQueue->xInUseWord = 0;
+}
+
+/* Array of LpEvent handler functions */
+extern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];
+unsigned long ItLpQueueInProcess = 0;
+
+struct HvLpEvent * ItLpQueue_getNextLpEvent( struct ItLpQueue * lpQueue )
+{
+ struct HvLpEvent * nextLpEvent =
+ (struct HvLpEvent *)lpQueue->xSlicCurEventPtr;
+ if ( nextLpEvent->xFlags.xValid ) {
+ /* Set pointer to next potential event */
+ lpQueue->xSlicCurEventPtr += ((nextLpEvent->xSizeMinus1 +
+ LpEventAlign ) /
+ LpEventAlign ) *
+ LpEventAlign;
+ /* Wrap to beginning if no room at end */
+ if (lpQueue->xSlicCurEventPtr > lpQueue->xSlicLastValidEventPtr)
+ lpQueue->xSlicCurEventPtr = lpQueue->xSlicEventStackPtr;
+ }
+ else
+ nextLpEvent = NULL;
+
+ return nextLpEvent;
+}
+
+int ItLpQueue_isLpIntPending( struct ItLpQueue * lpQueue )
+{
+ int retval = 0;
+ struct HvLpEvent * nextLpEvent;
+ if ( lpQueue ) {
+ nextLpEvent = (struct HvLpEvent *)lpQueue->xSlicCurEventPtr;
+ retval = nextLpEvent->xFlags.xValid | lpQueue->xPlicOverflowIntPending;
+ }
+ return retval;
+}
+
+void ItLpQueue_clearValid( struct HvLpEvent * event )
+{
+ /* Clear the valid bit of the event
+ * Also clear bits within this event that might
+ * look like valid bits (on 64-byte boundaries)
+ */
+ unsigned extra = (( event->xSizeMinus1 + LpEventAlign ) /
+ LpEventAlign ) - 1;
+ switch ( extra ) {
+ case 3:
+ ((struct HvLpEvent*)((char*)event+3*LpEventAlign))->xFlags.xValid=0;
+ case 2:
+ ((struct HvLpEvent*)((char*)event+2*LpEventAlign))->xFlags.xValid=0;
+ case 1:
+ ((struct HvLpEvent*)((char*)event+1*LpEventAlign))->xFlags.xValid=0;
+ case 0:
+ ;
+ }
+ mb();
+ event->xFlags.xValid = 0;
+}
+
+unsigned ItLpQueue_process( struct ItLpQueue * lpQueue, struct pt_regs *regs )
+{
+ unsigned numIntsProcessed = 0;
+ struct HvLpEvent * nextLpEvent;
+
+ /* If we have recursed, just return */
+ if ( !set_inUse( lpQueue ) )
+ return 0;
+
+ if (ItLpQueueInProcess == 0)
+ ItLpQueueInProcess = 1;
+ else
+ BUG();
+
+ for (;;) {
+ nextLpEvent = ItLpQueue_getNextLpEvent( lpQueue );
+ if ( nextLpEvent ) {
+ /* Count events to return to caller
+ * and count processed events in lpQueue
+ */
+ ++numIntsProcessed;
+ lpQueue->xLpIntCount++;
+ /* Call appropriate handler here, passing
+ * a pointer to the LpEvent. The handler
+ * must make a copy of the LpEvent if it
+ * needs it in a bottom half. (perhaps for
+ * an ACK)
+ *
+ * Handlers are responsible for ACK processing
+ *
+ * The Hypervisor guarantees that LpEvents will
+ * only be delivered with types that we have
+ * registered for, so no type check is necessary
+ * here!
+ */
+ if ( nextLpEvent->xType < HvLpEvent_Type_NumTypes )
+ lpQueue->xLpIntCountByType[nextLpEvent->xType]++;
+ if ( nextLpEvent->xType < HvLpEvent_Type_NumTypes &&
+ lpEventHandler[nextLpEvent->xType] )
+ lpEventHandler[nextLpEvent->xType](nextLpEvent, regs);
+ else
+ printk(KERN_INFO "Unexpected Lp Event type=%d\n", nextLpEvent->xType );
+
+ ItLpQueue_clearValid( nextLpEvent );
+ }
+ else /* No more valid events
+ * If overflow events are pending
+ * process them
+ */
+ if ( lpQueue->xPlicOverflowIntPending ) {
+ HvCallEvent_getOverflowLpEvents(
+ lpQueue->xIndex);
+ }
+ else /* If nothing left then we are done */
+ break;
+ }
+
+ ItLpQueueInProcess = 0;
+ mb();
+ clear_inUse( lpQueue );
+
+ get_paca()->lpEvent_count += numIntsProcessed;
+
+ return numIntsProcessed;
+}
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/LparData.c linuxppc64_2_4/arch/ppc64/kernel/LparData.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/LparData.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/LparData.c Tue Dec 18 01:09:09 2001
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2001 Mike Corrigan, IBM Corp
+ *
+ * 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.
+ */
+#define __KERNEL__ 1
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+extern char _start_boltedStacks[];
+
+/* The LparMap data is now located at offset 0x6000 in head.S
+ * It was put there so that the HvReleaseData could address it
+ * with a 32-bit offset as required by the iSeries hypervisor
+ *
+ * The Naca has a pointer to the ItVpdAreas. The hypervisor finds
+ * the Naca via the HvReleaseData area. The HvReleaseData has the
+ * offset into the Naca of the pointer to the ItVpdAreas.
+ */
+
+extern struct ItVpdAreas itVpdAreas;
+
+/* The LpQueue is used to pass event data from the hypervisor to
+ * the partition. This is where I/O interrupt events are communicated.
+ * The ItLpQueue must be initialized (even though only to all zeros)
+ * If it were uninitialized (in .bss) it would get zeroed after the
+ * kernel gets control. The hypervisor will have filled in some fields
+ * before the kernel gets control. By initializing it we keep it out
+ * of the .bss
+ */
+
+struct ItLpQueue xItLpQueue = {};
+
+
+/* The HvReleaseData is the root of the information shared between
+ * the hypervisor and Linux.
+ */
+
+struct HvReleaseData hvReleaseData = {
+ 0xc8a5d9c4, /* desc = "HvRD" ebcdic */
+ sizeof(struct HvReleaseData),
+ offsetof(struct Naca, xItVpdAreas),
+ (struct Naca *)(KERNELBASE+0x4000), /* 64-bit Naca address */
+ 0x6000, /* offset of LparMap within loadarea (see head.S) */
+ 0,
+ 1, /* tags inactive */
+ 0, /* 64 bit */
+ 0, /* shared processors */
+ 0, /* HMT allowed */
+ 6, /* TEMP: This allows non-GA driver */
+ 4, /* We are v5r2m0 */
+ 3, /* Min supported PLIC = v5r1m0 */
+ 3, /* Min usuable PLIC = v5r1m0 */
+ { 0xd3, 0x89, 0x95, 0xa4, /* "Linux 2.4 "*/
+ 0xa7, 0x40, 0xf2, 0x4b,
+ 0xf4, 0x4b, 0xf6, 0xf4 },
+ {0}
+};
+
+extern void SystemReset_Iseries(void);
+extern void MachineCheck_Iseries(void);
+extern void DataAccess_Iseries(void);
+extern void InstructionAccess_Iseries(void);
+extern void HardwareInterrupt_Iseries(void);
+extern void Alignment_Iseries(void);
+extern void ProgramCheck_Iseries(void);
+extern void FPUnavailable_Iseries(void);
+extern void Decrementer_Iseries(void);
+extern void Trap_0a_Iseries(void);
+extern void Trap_0b_Iseries(void);
+extern void SystemCall_Iseries(void);
+extern void SingleStep_Iseries(void);
+extern void Trap_0e_Iseries(void);
+extern void PerformanceMonitor_Iseries(void);
+extern void DataAccessSLB_Iseries(void);
+extern void InstructionAccessSLB_Iseries(void);
+
+struct ItLpNaca itLpNaca = {
+ 0xd397d581, /* desc = "LpNa" ebcdic */
+ 0x0400, /* size of ItLpNaca */
+ 0x0300, 19, /* offset to int array, # ents */
+ 0, 0, 0, /* Part # of primary, serv, me */
+ 0, 0x100, /* # of LP queues, offset */
+ 0, 0, 0, /* Piranha stuff */
+ { 0,0,0,0,0 }, /* reserved */
+ 0,0,0,0,0,0,0, /* stuff */
+ { 0,0,0,0,0 }, /* reserved */
+ 0, /* reserved */
+ 0, /* VRM index of PLIC */
+ 0, 0, /* min supported, compat SLIC */
+ 0, /* 64-bit addr of load area */
+ 0, /* chunks for load area */
+ 0, 0, /* PASE mask, seg table */
+ { 0 }, /* 64 reserved bytes */
+ { 0 }, /* 128 reserved bytes */
+ { 0 }, /* Old LP Queue */
+ { 0 }, /* 384 reserved bytes */
+ {
+ (u64)SystemReset_Iseries, /* 0x100 System Reset */
+ (u64)MachineCheck_Iseries, /* 0x200 Machine Check */
+ (u64)DataAccess_Iseries, /* 0x300 Data Access */
+ (u64)InstructionAccess_Iseries, /* 0x400 Instruction Access */
+ (u64)HardwareInterrupt_Iseries, /* 0x500 External */
+ (u64)Alignment_Iseries, /* 0x600 Alignment */
+ (u64)ProgramCheck_Iseries, /* 0x700 Program Check */
+ (u64)FPUnavailable_Iseries, /* 0x800 FP Unavailable */
+ (u64)Decrementer_Iseries, /* 0x900 Decrementer */
+ (u64)Trap_0a_Iseries, /* 0xa00 Trap 0A */
+ (u64)Trap_0b_Iseries, /* 0xb00 Trap 0B */
+ (u64)SystemCall_Iseries, /* 0xc00 System Call */
+ (u64)SingleStep_Iseries, /* 0xd00 Single Step */
+ (u64)Trap_0e_Iseries, /* 0xe00 Trap 0E */
+ (u64)PerformanceMonitor_Iseries,/* 0xf00 Performance Monitor */
+ 0, /* int 0x1000 */
+ 0, /* int 0x1010 */
+ 0, /* int 0x1020 CPU ctls */
+ (u64)HardwareInterrupt_Iseries, /* SC Ret Hdlr */
+ (u64)DataAccessSLB_Iseries, /* 0x380 D-SLB */
+ (u64)InstructionAccessSLB_Iseries /* 0x480 I-SLB */
+ }
+};
+
+struct ItIplParmsReal xItIplParmsReal = {};
+
+struct IoHriProcessorVpd xIoHriProcessorVpd[maxProcessors] = {
+ {
+ xInstCacheOperandSize: 32,
+ xDataCacheOperandSize: 32,
+ xProcFreq: 50000000,
+ xTimeBaseFreq: 50000000,
+ xPVR: 0x3600
+ }
+};
+
+
+u64 xMsVpd[3400] = {}; /* Space for Main Store Vpd 27,200 bytes */
+
+u64 xRecoveryLogBuffer[32] = {}; /* Space for Recovery Log Buffer */
+
+struct SpCommArea xSpCommArea = {
+ 0xE2D7C3C2,
+ 1,
+ {0},
+ 0, 0, 0, 0, {0}
+};
+
+struct ItVpdAreas itVpdAreas = {
+ 0xc9a3e5c1, /* "ItVA" */
+ sizeof( struct ItVpdAreas ),
+ 0, 0,
+ 26, /* # VPD array entries */
+ 10, /* # DMA array entries */
+ maxProcessors*2, maxProcessors, /* Max logical, physical procs */
+ offsetof(struct ItVpdAreas,xPlicDmaToks),/* offset to DMA toks */
+ offsetof(struct ItVpdAreas,xSlicVpdAdrs),/* offset to VPD addrs */
+ offsetof(struct ItVpdAreas,xPlicDmaLens),/* offset to DMA lens */
+ offsetof(struct ItVpdAreas,xSlicVpdLens),/* offset to VPD lens */
+ 0, /* max slot labels */
+ 1, /* max LP queues */
+ {0}, {0}, /* reserved */
+ {0}, /* DMA lengths */
+ {0}, /* DMA tokens */
+ { /* VPD lengths */
+ 0,0,0,0, /* 0 - 3 */
+ sizeof(struct Paca), /* 4 length of Paca */
+ 0, /* 5 */
+ sizeof(struct ItIplParmsReal),/* 6 length of IPL parms */
+ 26992, /* 7 length of MS VPD */
+ 0, /* 8 */
+ sizeof(struct ItLpNaca),/* 9 length of LP Naca */
+ 0, /* 10 */
+ 256, /* 11 length of Recovery Log Buf */
+ sizeof(struct SpCommArea), /* 12 length of SP Comm Area */
+ 0,0,0, /* 13 - 15 */
+ sizeof(struct IoHriProcessorVpd),/* 16 length of Proc Vpd */
+ 0,0,0,0,0,0, /* 17 - 22 */
+ sizeof(struct ItLpQueue),/* 23 length of Lp Queue */
+ 0,0 /* 24 - 25 */
+ },
+ { /* VPD addresses */
+ 0,0,0,0, /* 0 - 3 */
+ &xPaca[0], /* 4 first Paca */
+ 0, /* 5 */
+ &xItIplParmsReal, /* 6 IPL parms */
+ &xMsVpd, /* 7 MS Vpd */
+ 0, /* 8 */
+ &itLpNaca, /* 9 LpNaca */
+ 0, /* 10 */
+ &xRecoveryLogBuffer, /* 11 Recovery Log Buffer */
+ &xSpCommArea, /* 12 SP Comm Area */
+ 0,0,0, /* 13 - 15 */
+ &xIoHriProcessorVpd, /* 16 Proc Vpd */
+ 0,0,0,0,0,0, /* 17 - 22 */
+ &xItLpQueue, /* 23 Lp Queue */
+ 0,0
+ }
+};
+
+
+/* Data area used in flush_hash_page */
+long long flush_hash_page_hpte[2];
+
+struct msChunks msChunks = {0, 0, 0, 0, NULL};
+
+/* Depending on whether this is called from iSeries or pSeries setup
+ * code, the location of the msChunks struct may or may not have
+ * to be reloc'd, so we force the caller to do that for us by passing
+ * in a pointer to the structure.
+ */
+unsigned long
+msChunks_alloc(unsigned long mem, unsigned long num_chunks, unsigned long chunk_size)
+{
+ unsigned long offset = reloc_offset();
+ struct msChunks *_msChunks = PTRRELOC(&msChunks);
+
+ _msChunks->num_chunks = num_chunks;
+ _msChunks->chunk_size = chunk_size;
+ _msChunks->chunk_shift = __ilog2(chunk_size);
+ _msChunks->chunk_mask = (1UL<<_msChunks->chunk_shift)-1;
+
+ mem = _ALIGN(mem, sizeof(msChunks_entry));
+ _msChunks->abs = (msChunks_entry *)(mem + offset);
+ mem += num_chunks * sizeof(msChunks_entry);
+
+ return mem;
+}
+
+
+
+
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/Makefile linuxppc64_2_4/arch/ppc64/kernel/Makefile
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/Makefile Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/Makefile Mon Nov 19 23:01:28 2001
@@ -0,0 +1,77 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+USE_STANDARD_AS_RULE := true
+
+EXTRA_CFLAGS = -mno-minimal-toc
+
+KHEAD := head.o
+
+all: $(KHEAD) kernel.o
+
+O_TARGET := kernel.o
+
+export-objs := ppc_ksyms.o setup.o
+
+obj-y := ppc_ksyms.o setup.o entry.o traps.o irq.o idle.o \
+ time.o process.o signal.o syscalls.o misc.o ptrace.o \
+ align.o semaphore.o bitops.o stab.o htab.o pacaData.o \
+ LparData.o udbg.o binfmt_elf32.o sys_ppc32.o sys32.o \
+ ioctl32.o ptrace32.o signal32.o open_pic.o xics.o \
+ pmc.o mf_proc.o proc_pmc.o proc_pcifr.o iSeries_setup.o \
+ ItLpQueue.o hvCall.o mf.o HvLpEvent.o ras.o \
+ iSeries_proc.o HvCall.o flight_recorder.o HvLpConfig.o \
+ rtc.o
+
+obj-$(CONFIG_PCI) += pci.o pci_dn.o pci_dma.o
+obj-$(CONFIG_PPC_EEH) += eeh.o
+
+ifeq ($(CONFIG_PPC_ISERIES),y)
+obj-$(CONFIG_PCI) += iSeries_pci.o iSeries_pci_reset.o iSeries_IoMmTable.o iSeries_irq.o iSeries_VpdInfo.o XmPciLpEvent.o
+endif
+ifeq ($(CONFIG_PPC_PSERIES),y)
+obj-$(CONFIG_PCI) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o
+
+obj-y += rtasd.o
+endif
+
+obj-$(CONFIG_KGDB) += ppc-stub.o
+
+obj-$(CONFIG_SMP) += smp.o
+
+# tibit: for matrox_init2()
+ifeq ($(CONFIG_NVRAM),y)
+ obj-$(CONFIG_NVRAM) += pmac_nvram.o
+endif
+
+obj-y += prom.o lmb.o rtas.o rtas-proc.o chrp_setup.o i8259.o
+
+include $(TOPDIR)/Rules.make
+
+#
+# This is just to get the dependencies...
+#
+
+head.o: head.S ppc_defs.h
+
+ppc_defs.h: mk_defs.c ppc_defs.head \
+ $(TOPDIR)/include/asm/mmu.h \
+ $(TOPDIR)/include/asm/processor.h \
+ $(TOPDIR)/include/asm/pgtable.h \
+ $(TOPDIR)/include/asm/ptrace.h
+ $(CC) $(CFLAGS) -S mk_defs.c
+ cp ppc_defs.head ppc_defs.h
+# for bk, this way we can write to the file even if it's not checked out
+ chmod u+w ppc_defs.h
+ grep '^#define' mk_defs.s >> ppc_defs.h
+ rm mk_defs.s
+
+checks: checks.c
+ $(HOSTCC) -I$(HPATH) $(HOSTCFLAGS) -D__KERNEL__ -fno-builtin -o checks checks.c
+ ./checks
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/XmPciLpEvent.c linuxppc64_2_4/arch/ppc64/kernel/XmPciLpEvent.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/XmPciLpEvent.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/XmPciLpEvent.c Tue Dec 18 01:09:09 2001
@@ -0,0 +1,157 @@
+/*
+ * File XmPciLpEvent.h created by Wayne Holm on Mon Jan 15 2001.
+ *
+ * This module handles PCI interrupt events sent by the iSeries Hypervisor.
+*/
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+long Pci_Interrupt_Count = 0;
+long Pci_Event_Count = 0;
+
+enum XmPciLpEvent_Subtype {
+ XmPciLpEvent_BusCreated = 0, // PHB has been created
+ XmPciLpEvent_BusFailed = 1, // PHB has failed
+ XmPciLpEvent_BusRecovered = 12, // PHB has been recovered
+ XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed
+ XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered
+ XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt
+};
+
+struct XmPciLpEvent_BusInterrupt {
+ HvBusNumber busNumber;
+ HvSubBusNumber subBusNumber;
+};
+
+struct XmPciLpEvent_NodeInterrupt {
+ HvBusNumber busNumber;
+ HvSubBusNumber subBusNumber;
+ HvAgentId deviceId;
+};
+
+struct XmPciLpEvent {
+ struct HvLpEvent hvLpEvent;
+
+ union {
+ u64 alignData; // Align on an 8-byte boundary
+
+ struct {
+ u32 fisr;
+ HvBusNumber busNumber;
+ HvSubBusNumber subBusNumber;
+ HvAgentId deviceId;
+ } slotInterrupt;
+
+ struct XmPciLpEvent_BusInterrupt busFailed;
+ struct XmPciLpEvent_BusInterrupt busRecovered;
+ struct XmPciLpEvent_BusInterrupt busCreated;
+
+ struct XmPciLpEvent_NodeInterrupt nodeFailed;
+ struct XmPciLpEvent_NodeInterrupt nodeRecovered;
+
+ } eventData;
+
+};
+
+static void intReceived(struct XmPciLpEvent* eventParm, struct pt_regs* regsParm);
+
+static void XmPciLpEvent_handler( struct HvLpEvent* eventParm, struct pt_regs* regsParm)
+{
+ //PPCDBG(PPCDBG_BUSWALK,"XmPciLpEvent_handler, type 0x%x\n",eventParm->xType );
+ ++Pci_Event_Count;
+
+ if (eventParm && eventParm->xType == HvLpEvent_Type_PciIo) {
+ switch( eventParm->xFlags.xFunction ) {
+ case HvLpEvent_Function_Int:
+ intReceived( (struct XmPciLpEvent*)eventParm, regsParm );
+ break;
+ case HvLpEvent_Function_Ack:
+ printk(KERN_ERR "XmPciLpEvent.c: unexpected ack received\n");
+ break;
+ default:
+ printk(KERN_ERR "XmPciLpEvent.c: unexpected event function %d\n",(int)eventParm->xFlags.xFunction);
+ break;
+ }
+ }
+ else if (event) {
+ printk(KERN_ERR "XmPciLpEvent.c: Unrecognized PCI event type 0x%x\n",(int)eventParm->xType);
+ }
+ else {
+ printk(KERN_ERR "XmPciLpEvent.c: NULL event received\n");
+ }
+}
+
+static void intReceived(struct XmPciLpEvent* eventParm, struct pt_regs* regsParm)
+{
+ int irq;
+
+ ++Pci_Interrupt_Count;
+ //PPCDBG(PPCDBG_BUSWALK,"PCI: XmPciLpEvent.c: intReceived\n");
+
+ switch (eventParm->hvLpEvent.xSubtype) {
+ case XmPciLpEvent_SlotInterrupt:
+ irq = eventParm->hvLpEvent.xCorrelationToken;
+ /* Dispatch the interrupt handlers for this irq */
+ ppc_irq_dispatch_handler(regsParm, irq);
+ HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
+ eventParm->eventData.slotInterrupt.subBusNumber,
+ eventParm->eventData.slotInterrupt.deviceId);
+ break;
+ /* Ignore error recovery events for now */
+ case XmPciLpEvent_BusCreated:
+ printk(KERN_INFO "XmPciLpEvent.c: system bus %d created\n", eventParm->eventData.busCreated.busNumber);
+ break;
+ case XmPciLpEvent_BusFailed:
+ printk(KERN_INFO "XmPciLpEvent.c: system bus %d failed\n", eventParm->eventData.busFailed.busNumber);
+ break;
+ case XmPciLpEvent_BusRecovered:
+ printk(KERN_INFO "XmPciLpEvent.c: system bus %d recovered\n", eventParm->eventData.busRecovered.busNumber);
+ break;
+ case XmPciLpEvent_NodeFailed:
+ printk(KERN_INFO "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d failed\n", eventParm->eventData.nodeFailed.busNumber, eventParm->eventData.nodeFailed.subBusNumber, eventParm->eventData.nodeFailed.deviceId);
+ break;
+ case XmPciLpEvent_NodeRecovered:
+ printk(KERN_INFO "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d recovered\n", eventParm->eventData.nodeRecovered.busNumber, eventParm->eventData.nodeRecovered.subBusNumber, eventParm->eventData.nodeRecovered.deviceId);
+ break;
+ default:
+ printk(KERN_ERR "XmPciLpEvent.c: unrecognized event subtype 0x%x\n",
+ eventParm->hvLpEvent.xSubtype);
+ break;
+ };
+}
+
+
+/* This should be called sometime prior to buswalk (init_IRQ would be good) */
+int XmPciLpEvent_init()
+{
+ int xRc;
+ PPCDBG(PPCDBG_BUSWALK,"XmPciLpEvent_init, Register Event type 0x%04X\n",HvLpEvent_Type_PciIo);
+
+ xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo, &XmPciLpEvent_handler);
+ if (xRc == 0) {
+ xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
+ if (xRc != 0) {
+ printk(KERN_ERR "XmPciLpEvent.c: open event path failed with rc 0x%x\n", xRc);
+ }
+ }
+ else {
+ printk(KERN_ERR "XmPciLpEvent.c: register handler failed with rc 0x%x\n", xRc);
+ }
+ return xRc;
+}
+
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/align.c linuxppc64_2_4/arch/ppc64/kernel/align.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/align.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/align.c Tue Dec 18 01:09:09 2001
@@ -0,0 +1,362 @@
+/*
+ * align.c - handle alignment exceptions for the Power PC.
+ *
+ * Copyright (c) 1996 Paul Mackerras
+ * Copyright (c) 1998-1999 TiVo, Inc.
+ * PowerPC 403GCX modifications.
+ * Copyright (c) 1999 Grant Erickson
+ * PowerPC 403GCX/405GP modifications.
+ * Copyright (c) 2001 PPC64 team, IBM Corp
+ *
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+struct aligninfo {
+ unsigned char len;
+ unsigned char flags;
+};
+
+#define OPCD(inst) (((inst) & 0xFC000000) >> 26)
+#define RS(inst) (((inst) & 0x03E00000) >> 21)
+#define RA(inst) (((inst) & 0x001F0000) >> 16)
+#define IS_DFORM(code) ((code) >= 32 && (code) <= 47)
+
+#define INVALID { 0, 0 }
+
+#define LD 1 /* load */
+#define ST 2 /* store */
+#define SE 4 /* sign-extend value */
+#define F 8 /* to/from fp regs */
+#define U 0x10 /* update index register */
+#define M 0x20 /* multiple load/store */
+#define S 0x40 /* single-precision fp, or byte-swap value */
+#define HARD 0x80 /* string, stwcx. */
+#define D 0x100 /* double-word load/store */
+
+#define DCBZ 0x5f /* 8xx/82xx dcbz faults when cache not enabled */
+
+/*
+ * The PowerPC stores certain bits of the instruction that caused the
+ * alignment exception in the DSISR register. This array maps those
+ * bits to information about the operand length and what the
+ * instruction would do.
+ */
+static struct aligninfo aligninfo[128] = {
+ { 4, LD }, /* 00 0 0000: lwz / lwarx */
+ INVALID, /* 00 0 0001 */
+ { 4, ST }, /* 00 0 0010: stw */
+ INVALID, /* 00 0 0011 */
+ { 2, LD }, /* 00 0 0100: lhz */
+ { 2, LD+SE }, /* 00 0 0101: lha */
+ { 2, ST }, /* 00 0 0110: sth */
+ { 4, LD+M }, /* 00 0 0111: lmw */
+ { 4, LD+F+S }, /* 00 0 1000: lfs */
+ { 8, LD+F }, /* 00 0 1001: lfd */
+ { 4, ST+F+S }, /* 00 0 1010: stfs */
+ { 8, ST+F }, /* 00 0 1011: stfd */
+ INVALID, /* 00 0 1100 */
+ { 8, LD }, /* 00 0 1101: ld */
+ INVALID, /* 00 0 1110 */
+ { 8, ST }, /* 00 0 1111: std */
+ { 4, LD+U }, /* 00 1 0000: lwzu */
+ INVALID, /* 00 1 0001 */
+ { 4, ST+U }, /* 00 1 0010: stwu */
+ INVALID, /* 00 1 0011 */
+ { 2, LD+U }, /* 00 1 0100: lhzu */
+ { 2, LD+SE+U }, /* 00 1 0101: lhau */
+ { 2, ST+U }, /* 00 1 0110: sthu */
+ { 4, ST+M }, /* 00 1 0111: stmw */
+ { 4, LD+F+S+U }, /* 00 1 1000: lfsu */
+ { 8, LD+F+U }, /* 00 1 1001: lfdu */
+ { 4, ST+F+S+U }, /* 00 1 1010: stfsu */
+ { 8, ST+F+U }, /* 00 1 1011: stfdu */
+ INVALID, /* 00 1 1100 */
+ { 8, ST }, /* 00 1 1101: std */
+ INVALID, /* 00 1 1110 */
+ INVALID, /* 00 1 1111 */
+ { 8, LD }, /* 01 0 0000: ldx */
+ INVALID, /* 01 0 0001 */
+ { 8, ST }, /* 01 0 0010: stdx */
+ INVALID, /* 01 0 0011 */
+ INVALID, /* 01 0 0100 */
+ INVALID, /* 01 0 0101: lwax?? */
+ INVALID, /* 01 0 0110 */
+ INVALID, /* 01 0 0111 */
+ { 0, LD+HARD }, /* 01 0 1000: lswx */
+ { 0, LD+HARD }, /* 01 0 1001: lswi */
+ { 0, ST+HARD }, /* 01 0 1010: stswx */
+ { 0, ST+HARD }, /* 01 0 1011: stswi */
+ INVALID, /* 01 0 1100 */
+ { 8, LD+U }, /* 01 0 1101: ldu */
+ INVALID, /* 01 0 1110 */
+ { 8, ST+U }, /* 01 0 1111: stdu */
+ { 8, LD+U }, /* 01 1 0000: ldux */
+ INVALID, /* 01 1 0001 */
+ { 8, ST+U }, /* 01 1 0010: stdux */
+ INVALID, /* 01 1 0011 */
+ INVALID, /* 01 1 0100 */
+ INVALID, /* 01 1 0101: lwaux?? */
+ INVALID, /* 01 1 0110 */
+ INVALID, /* 01 1 0111 */
+ INVALID, /* 01 1 1000 */
+ INVALID, /* 01 1 1001 */
+ INVALID, /* 01 1 1010 */
+ INVALID, /* 01 1 1011 */
+ INVALID, /* 01 1 1100 */
+ INVALID, /* 01 1 1101 */
+ INVALID, /* 01 1 1110 */
+ INVALID, /* 01 1 1111 */
+ INVALID, /* 10 0 0000 */
+ INVALID, /* 10 0 0001 */
+ { 0, ST+HARD }, /* 10 0 0010: stwcx. */
+ INVALID, /* 10 0 0011 */
+ INVALID, /* 10 0 0100 */
+ INVALID, /* 10 0 0101 */
+ INVALID, /* 10 0 0110 */
+ INVALID, /* 10 0 0111 */
+ { 4, LD+S }, /* 10 0 1000: lwbrx */
+ INVALID, /* 10 0 1001 */
+ { 4, ST+S }, /* 10 0 1010: stwbrx */
+ INVALID, /* 10 0 1011 */
+ { 2, LD+S }, /* 10 0 1100: lhbrx */
+ INVALID, /* 10 0 1101 */
+ { 2, ST+S }, /* 10 0 1110: sthbrx */
+ INVALID, /* 10 0 1111 */
+ INVALID, /* 10 1 0000 */
+ INVALID, /* 10 1 0001 */
+ INVALID, /* 10 1 0010 */
+ INVALID, /* 10 1 0011 */
+ INVALID, /* 10 1 0100 */
+ INVALID, /* 10 1 0101 */
+ INVALID, /* 10 1 0110 */
+ INVALID, /* 10 1 0111 */
+ INVALID, /* 10 1 1000 */
+ INVALID, /* 10 1 1001 */
+ INVALID, /* 10 1 1010 */
+ INVALID, /* 10 1 1011 */
+ INVALID, /* 10 1 1100 */
+ INVALID, /* 10 1 1101 */
+ INVALID, /* 10 1 1110 */
+ { 0, ST+HARD }, /* 10 1 1111: dcbz */
+ { 4, LD }, /* 11 0 0000: lwzx */
+ INVALID, /* 11 0 0001 */
+ { 4, ST }, /* 11 0 0010: stwx */
+ INVALID, /* 11 0 0011 */
+ { 2, LD }, /* 11 0 0100: lhzx */
+ { 2, LD+SE }, /* 11 0 0101: lhax */
+ { 2, ST }, /* 11 0 0110: sthx */
+ INVALID, /* 11 0 0111 */
+ { 4, LD+F+S }, /* 11 0 1000: lfsx */
+ { 8, LD+F }, /* 11 0 1001: lfdx */
+ { 4, ST+F+S }, /* 11 0 1010: stfsx */
+ { 8, ST+F }, /* 11 0 1011: stfdx */
+ INVALID, /* 11 0 1100 */
+ INVALID, /* 11 0 1101 */
+ INVALID, /* 11 0 1110 */
+ INVALID, /* 11 0 1111 */
+ { 4, LD+U }, /* 11 1 0000: lwzux */
+ INVALID, /* 11 1 0001 */
+ { 4, ST+U }, /* 11 1 0010: stwux */
+ INVALID, /* 11 1 0011 */
+ { 2, LD+U }, /* 11 1 0100: lhzux */
+ { 2, LD+SE+U }, /* 11 1 0101: lhaux */
+ { 2, ST+U }, /* 11 1 0110: sthux */
+ INVALID, /* 11 1 0111 */
+ { 4, LD+F+S+U }, /* 11 1 1000: lfsux */
+ { 8, LD+F+U }, /* 11 1 1001: lfdux */
+ { 4, ST+F+S+U }, /* 11 1 1010: stfsux */
+ { 8, ST+F+U }, /* 11 1 1011: stfdux */
+ INVALID, /* 11 1 1100 */
+ INVALID, /* 11 1 1101 */
+ INVALID, /* 11 1 1110 */
+ INVALID, /* 11 1 1111 */
+};
+
+#define SWAP(a, b) (t = (a), (a) = (b), (b) = t)
+
+int
+fix_alignment(struct pt_regs *regs)
+{
+ int instr, nb, flags;
+ int opcode, f1, f2, f3;
+ int i, t;
+ int reg, areg;
+ unsigned char *addr;
+ union {
+ int l;
+ long ll;
+ float f;
+ double d;
+ unsigned char v[8];
+ } data;
+
+ if (__is_processor(PV_POWER4)) {
+ /*
+ * The POWER4 has a DSISR register but doesn't set it on
+ * an alignment fault. -- paulus
+ */
+
+ instr = *((unsigned int *)regs->nip);
+ opcode = OPCD(instr);
+ reg = RS(instr);
+ areg = RA(instr);
+
+ if (IS_DFORM(opcode)) {
+ f1 = 0;
+ f2 = (instr & 0x04000000) >> 26;
+ f3 = (instr & 0x78000000) >> 27;
+ } else {
+ f1 = (instr & 0x00000006) >> 1;
+ f2 = (instr & 0x00000040) >> 6;
+ f3 = (instr & 0x00000780) >> 7;
+ }
+
+ instr = ((f1 << 5) | (f2 << 4) | f3);
+ } else {
+ reg = (regs->dsisr >> 5) & 0x1f; /* source/dest register */
+ areg = regs->dsisr & 0x1f; /* register to update */
+ instr = (regs->dsisr >> 10) & 0x7f;
+ instr |= (regs->dsisr >> 13) & 0x60;
+ }
+
+ nb = aligninfo[instr].len;
+ if (nb == 0) {
+ long *p;
+ int i;
+
+ if (instr != DCBZ)
+ return 0; /* too hard or invalid instruction */
+ /*
+ * The dcbz (data cache block zero) instruction
+ * gives an alignment fault if used on non-cacheable
+ * memory. We handle the fault mainly for the
+ * case when we are running with the cache disabled
+ * for debugging.
+ */
+ p = (long *) (regs->dar & -L1_CACHE_BYTES);
+ for (i = 0; i < L1_CACHE_BYTES / sizeof(long); ++i)
+ p[i] = 0;
+ return 1;
+ }
+
+ flags = aligninfo[instr].flags;
+ addr = (unsigned char *)regs->dar;
+
+ /* Verify the address of the operand */
+ if (user_mode(regs)) {
+ if (verify_area((flags & ST? VERIFY_WRITE: VERIFY_READ), addr, nb))
+ return -EFAULT; /* bad address */
+ }
+
+ if ((flags & F) && (regs->msr & MSR_FP))
+ giveup_fpu(current);
+ if (flags & M)
+ return 0; /* too hard for now */
+
+ /* If we read the operand, copy it in */
+ if (flags & LD) {
+ if (nb == 2) {
+ data.v[0] = data.v[1] = 0;
+ if (__get_user(data.v[2], addr)
+ || __get_user(data.v[3], addr+1))
+ return -EFAULT;
+ } else {
+ for (i = 0; i < nb; ++i)
+ if (__get_user(data.v[i], addr+i))
+ return -EFAULT;
+ }
+ }
+ /* Unfortunately D (== 0x100) doesn't fit in the aligninfo[n].flags
+ field. So synthesize it here. */
+ if ((flags & F) == 0 && nb == 8)
+ flags |= D;
+
+ switch (flags & ~U) {
+ case LD+SE:
+ if (data.v[2] >= 0x80)
+ data.v[0] = data.v[1] = -1;
+ /* fall through */
+ case LD:
+ regs->gpr[reg] = data.l;
+ break;
+ case LD+D:
+ regs->gpr[reg] = data.ll;
+ break;
+ case LD+S:
+ if (nb == 2) {
+ SWAP(data.v[2], data.v[3]);
+ } else {
+ SWAP(data.v[0], data.v[3]);
+ SWAP(data.v[1], data.v[2]);
+ }
+ regs->gpr[reg] = data.l;
+ break;
+ case ST:
+ data.l = regs->gpr[reg];
+ break;
+ case ST+D:
+ data.ll = regs->gpr[reg];
+ break;
+ case ST+S:
+ data.l = regs->gpr[reg];
+ if (nb == 2) {
+ SWAP(data.v[2], data.v[3]);
+ } else {
+ SWAP(data.v[0], data.v[3]);
+ SWAP(data.v[1], data.v[2]);
+ }
+ break;
+ case LD+F:
+ current->thread.fpr[reg] = data.d;
+ break;
+ case ST+F:
+ data.d = current->thread.fpr[reg];
+ break;
+ /* these require some floating point conversions... */
+ /* we'd like to use the assignment, but we have to compile
+ * the kernel with -msoft-float so it doesn't use the
+ * fp regs for copying 8-byte objects. */
+ case LD+F+S:
+ enable_kernel_fp();
+ cvt_fd(&data.f, ¤t->thread.fpr[reg], ¤t->thread.fpscr);
+ /* current->thread.fpr[reg] = data.f; */
+ break;
+ case ST+F+S:
+ enable_kernel_fp();
+ cvt_df(¤t->thread.fpr[reg], &data.f, ¤t->thread.fpscr);
+ /* data.f = current->thread.fpr[reg]; */
+ break;
+ default:
+ printk("align: can't handle flags=%x\n", flags);
+ return 0;
+ }
+
+ if (flags & ST) {
+ if (nb == 2) {
+ if (__put_user(data.v[2], addr)
+ || __put_user(data.v[3], addr+1))
+ return -EFAULT;
+ } else {
+ for (i = 0; i < nb; ++i)
+ if (__put_user(data.v[i], addr+i))
+ return -EFAULT;
+ }
+ }
+
+ if (flags & U) {
+ regs->gpr[areg] = regs->dar;
+ }
+
+ return 1;
+}
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/binfmt_elf32.c linuxppc64_2_4/arch/ppc64/kernel/binfmt_elf32.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/binfmt_elf32.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/binfmt_elf32.c Thu Oct 18 04:27:04 2001
@@ -0,0 +1,79 @@
+/*
+ * binfmt_elf32.c: Support 32-bit PPC ELF binaries on Power3 and followons.
+ * based on the SPARC64 version.
+ * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz)
+ *
+ * Copyright (C) 2000,2001 Ken Aaker (kdaaker@rchland.vnet.ibm.com), IBM Corp
+ * Copyright (C) 2001 Anton Blanchard (anton@au.ibm.com), IBM
+ *
+ * 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.
+ */
+
+#define ELF_ARCH EM_PPC
+#define ELF_CLASS ELFCLASS32
+#define ELF_DATA ELFDATA2MSB;
+
+#include
+#include
+#include
+#include
+
+struct timeval32
+{
+ int tv_sec, tv_usec;
+};
+
+#define elf_prstatus elf_prstatus32
+struct elf_prstatus32
+{
+ struct elf_siginfo pr_info; /* Info associated with signal */
+ short pr_cursig; /* Current signal */
+ unsigned int pr_sigpend; /* Set of pending signals */
+ unsigned int pr_sighold; /* Set of held signals */
+ pid_t pr_pid;
+ pid_t pr_ppid;
+ pid_t pr_pgrp;
+ pid_t pr_sid;
+ struct timeval32 pr_utime; /* User time */
+ struct timeval32 pr_stime; /* System time */
+ struct timeval32 pr_cutime; /* Cumulative user time */
+ struct timeval32 pr_cstime; /* Cumulative system time */
+ elf_gregset_t pr_reg; /* General purpose registers. */
+ int pr_fpvalid; /* True if math co-processor being used. */
+};
+
+#define elf_prpsinfo elf_prpsinfo32
+struct elf_prpsinfo32
+{
+ char pr_state; /* numeric process state */
+ char pr_sname; /* char for pr_state */
+ char pr_zomb; /* zombie */
+ char pr_nice; /* nice val */
+ unsigned int pr_flag; /* flags */
+ u32 pr_uid;
+ u32 pr_gid;
+ pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
+ /* Lots missing */
+ char pr_fname[16]; /* filename of executable */
+ char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
+};
+
+extern void start_thread32(struct pt_regs *, unsigned long, unsigned long);
+#undef start_thread
+#define start_thread start_thread32
+#define init_elf_binfmt init_elf32_binfmt
+
+#undef CONFIG_BINFMT_ELF
+#ifdef CONFIG_BINFMT_ELF32
+#define CONFIG_BINFMT_ELF CONFIG_BINFMT_ELF32
+#endif
+#undef CONFIG_BINFMT_ELF_MODULE
+#ifdef CONFIG_BINFMT_ELF32_MODULE
+#define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE
+#endif
+
+#include "../../../fs/binfmt_elf.c"
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/bitops.c linuxppc64_2_4/arch/ppc64/kernel/bitops.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/bitops.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/bitops.c Tue Dec 18 01:09:09 2001
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ * Adapted for ppc64 - Todd Inglett, Anton Blanchard
+ *
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#undef DEBUG_BITOPS
+
+/*
+ * Bitops are weird when viewed on big-endian systems. They were designed
+ * on little endian so the size of the bitset doesn't matter (low order bytes
+ * come first) as long as the bit in question is valid.
+ *
+ * Bits are "tested" often using the C expression (val & (1<> 6);
+ unsigned long result = offset & ~63UL;
+ unsigned long tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset &= 63UL;
+
+ if (offset) {
+ tmp = *p++;
+ tmp |= ~0UL >> (64-offset);
+ if (size < 64)
+ goto found_first;
+ if (~tmp)
+ goto found_middle;
+ size -= 64;
+ result += 64;
+ }
+ while (size & ~63UL) {
+ if (~(tmp = *(p++)))
+ goto found_middle;
+ result += 64;
+ size -= 64;
+ }
+ if (!size)
+ return result;
+ tmp = *p;
+
+found_first:
+ tmp |= ~0UL << size;
+ if (tmp == ~0UL)
+ return result+size;
+found_middle:
+ return result + ffz(tmp);
+}
+
+void BUG_OUTLINE(char* file, unsigned line)
+{
+ udbg_printf("BUG - kernel BUG at %s:%d! \n", __FILE__, __LINE__);
+ PPCDBG_ENTER_DEBUGGER();
+ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__);
+ __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR);
+}
+
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/checks.c linuxppc64_2_4/arch/ppc64/kernel/checks.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/checks.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/checks.c Mon Jun 4 20:06:03 2001
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2001 PPC 64 Team, IBM Corp
+ *
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+/*
+ * Do various before compile checks of data structures
+ *
+ * This is invoked when you do a make checks
+ * Is this enough or are there more things that we would like to do here?
+ * -- tgall
+ */
+int main(void)
+{
+ int ret = 0;
+#if 0
+ if ( sizeof(struct thread_struct) % 16 )
+ {
+ printf("Thread struct is not modulo 16 bytes: "
+ "%d bytes total, %d bytes off\n",
+ sizeof(struct thread_struct),
+ sizeof(struct thread_struct)%16);
+ ret = -1;
+ }
+#endif
+
+ if ( sizeof(struct pt_regs) % 16 )
+ {
+ printf("pt_regs struct is not modulo 16 bytes: "
+ "%d bytes total, %d bytes off\n",
+ sizeof(struct pt_regs),
+ sizeof(struct pt_regs)%16);
+ ret = -1;
+
+ }
+
+ printf("Task size : %d bytes\n"
+ "Tss size : %d bytes\n"
+ "pt_regs size : %d bytes\n"
+ "Kernel stack size: %d bytes\n",
+ sizeof(struct task_struct), sizeof(struct thread_struct),
+ sizeof(struct pt_regs),
+ sizeof(union task_union) - sizeof(struct task_struct));
+ return ret;
+}
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/chrp_setup.c linuxppc64_2_4/arch/ppc64/kernel/chrp_setup.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/chrp_setup.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/chrp_setup.c Thu Feb 21 20:54:05 2002
@@ -0,0 +1,389 @@
+/*
+ * linux/arch/ppc/kernel/setup.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Adapted from 'alpha' version by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * Modified by PPC64 Team, IBM Corp
+ *
+ * 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.
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "local_irq.h"
+#include "i8259.h"
+#include "open_pic.h"
+#include "xics.h"
+#include
+
+extern volatile unsigned char *chrp_int_ack_special;
+extern struct Naca *naca;
+
+void chrp_setup_pci_ptrs(void);
+void chrp_progress(char *, unsigned short);
+void chrp_request_regions(void);
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+extern unsigned char pckbd_sysrq_xlate[128];
+extern void openpic_init_IRQ(void);
+extern void init_ras_IRQ(void);
+
+extern void find_and_init_phbs(void);
+extern void pSeries_pcibios_fixup(void);
+extern void iSeries_pcibios_fixup(void);
+
+extern void pSeries_get_rtc_time(struct rtc_time *rtc_time);
+extern int pSeries_set_rtc_time(struct rtc_time *rtc_time);
+void pSeries_calibrate_decr(void);
+
+kdev_t boot_dev;
+unsigned long virtPython0Facilities = 0; // python0 facility area (memory mapped io) (64-bit format) VIRTUAL address.
+
+extern HPTE *Hash, *Hash_end;
+extern unsigned long Hash_size, Hash_mask;
+extern int probingmem;
+extern unsigned long loops_per_jiffy;
+
+#ifdef CONFIG_BLK_DEV_RAM
+extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start; /* starting block # of image */
+#endif
+
+void
+chrp_get_cpuinfo(struct seq_file *m)
+{
+ struct device_node *root;
+ const char *model = "";
+
+ root = find_path_device("/");
+ if (root)
+ model = get_property(root, "model", NULL);
+ seq_printf(m, "machine\t\t: CHRP %s\n", model);
+}
+
+void __init chrp_request_regions(void) {
+ request_region(0x20,0x20,"pic1");
+ request_region(0xa0,0x20,"pic2");
+ request_region(0x00,0x20,"dma1");
+ request_region(0x40,0x20,"timer");
+ request_region(0x80,0x10,"dma page reg");
+ request_region(0xc0,0x20,"dma2");
+}
+
+void __init
+chrp_setup_arch(void)
+{
+ extern char cmd_line[];
+ struct device_node *root;
+ unsigned int *opprop;
+
+ /* openpic global configuration register (64-bit format). */
+ /* openpic Interrupt Source Unit pointer (64-bit format). */
+ /* python0 facility area (mmio) (64-bit format) REAL address. */
+
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* this is fine for chrp */
+ initrd_below_start_ok = 1;
+
+ if (initrd_start)
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+ else
+#endif
+ ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */
+
+ printk("Boot arguments: %s\n", cmd_line);
+
+ /* Find and initialize PCI host bridges */
+ /* iSeries needs to be done much later. */
+ #ifndef CONFIG_PPC_ISERIES
+ find_and_init_phbs();
+ #endif
+
+ /* Find the Open PIC if present */
+ root = find_path_device("/");
+ opprop = (unsigned int *) get_property(root,
+ "platform-open-pic", NULL);
+ if (opprop != 0) {
+ int n = prom_n_addr_cells(root);
+ unsigned long openpic;
+
+ for (openpic = 0; n > 0; --n)
+ openpic = (openpic << 32) + *opprop++;
+ printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic);
+ udbg_printf("OpenPIC addr: %lx\n", openpic);
+ OpenPIC_Addr = __ioremap(openpic, 0x40000, _PAGE_NO_CACHE);
+ }
+
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#endif
+}
+
+void __init
+chrp_init2(void)
+{
+ /*
+ * It is sensitive, when this is called (not too earlu)
+ * -- tibit
+ */
+ chrp_request_regions();
+ ppc_md.progress(UTS_RELEASE, 0x7777);
+}
+
+
+/* Early initialization. Relocation is on but do not reference unbolted pages */
+void __init pSeries_init_early(void)
+{
+#ifdef CONFIG_PPC_PSERIES /* This ifdef should go away */
+ void *comport;
+
+ hpte_init_pSeries();
+ tce_init_pSeries();
+ pSeries_pcibios_init_early();
+
+#ifdef CONFIG_SMP
+ smp_init_pSeries();
+#endif
+
+ /* Map the uart for udbg. */
+ comport = (void *)__ioremap(naca->serialPortAddr, 16, _PAGE_NO_CACHE);
+ udbg_init_uart(comport);
+
+ ppc_md.udbg_putc = udbg_putc;
+ ppc_md.udbg_getc = udbg_getc;
+ ppc_md.udbg_getc_poll = udbg_getc_poll;
+#endif
+}
+
+void __init
+chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+#if 0 /* PPPBBB remove this later... -Peter */
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if ( r6 )
+ {
+ initrd_start = __va(r6);
+ initrd_end = __va(r6 + r7);
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+#endif
+
+ ppc_md.ppc_machine = _machine;
+
+ ppc_md.setup_arch = chrp_setup_arch;
+ ppc_md.setup_residual = NULL;
+ ppc_md.get_cpuinfo = chrp_get_cpuinfo;
+ if(naca->interrupt_controller == IC_OPEN_PIC) {
+ ppc_md.init_IRQ = openpic_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+ ppc_md.post_irq = NULL;
+ } else {
+ ppc_md.init_IRQ = xics_init_IRQ;
+ ppc_md.get_irq = xics_get_irq;
+ ppc_md.post_irq = NULL;
+ }
+ ppc_md.init_ras_IRQ = init_ras_IRQ;
+
+ #ifndef CONFIG_PPC_ISERIES
+ ppc_md.pcibios_fixup = pSeries_pcibios_fixup;
+ #else
+ ppc_md.pcibios_fixup = NULL;
+ // ppc_md.pcibios_fixup = iSeries_pcibios_fixup;
+ #endif
+
+
+ ppc_md.init = chrp_init2;
+
+ ppc_md.restart = rtas_restart;
+ ppc_md.power_off = rtas_power_off;
+ ppc_md.halt = rtas_halt;
+
+ ppc_md.time_init = NULL;
+ ppc_md.get_boot_time = pSeries_get_rtc_time;
+ ppc_md.get_rtc_time = pSeries_get_rtc_time;
+ ppc_md.set_rtc_time = pSeries_set_rtc_time;
+ ppc_md.calibrate_decr = pSeries_calibrate_decr;
+
+ ppc_md.progress = chrp_progress;
+
+#ifdef CONFIG_VT
+ ppc_md.kbd_setkeycode = pckbd_setkeycode;
+ ppc_md.kbd_getkeycode = pckbd_getkeycode;
+ ppc_md.kbd_translate = pckbd_translate;
+ ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+ ppc_md.kbd_leds = pckbd_leds;
+ ppc_md.kbd_init_hw = pckbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
+ SYSRQ_KEY = 0x63; /* Print Screen */
+#endif
+#endif
+
+ ppc_md.progress("Linux ppc64\n", 0x0);
+}
+
+void __chrp
+chrp_progress(char *s, unsigned short hex)
+{
+ struct device_node *root;
+ int width, *p;
+ char *os;
+ static int display_character, set_indicator;
+ static int max_width;
+
+ if (hex)
+ udbg_printf(" %s\n", s);
+
+ if (!rtas.base || (_machine != _MACH_pSeries))
+ return;
+
+ if (max_width == 0) {
+ if ( (root = find_path_device("/rtas")) &&
+ (p = (unsigned int *)get_property(root,
+ "ibm,display-line-length",
+ NULL)) )
+ max_width = *p;
+ else
+ max_width = 0x10;
+ display_character = rtas_token("display-character");
+ set_indicator = rtas_token("set-indicator");
+ }
+ if (display_character == RTAS_UNKNOWN_SERVICE) {
+ /* use hex display */
+ if (set_indicator == RTAS_UNKNOWN_SERVICE)
+ return;
+ rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);
+ return;
+ }
+
+ rtas_call(display_character, 1, 1, NULL, '\r');
+
+ width = max_width;
+ os = s;
+ while ( *os )
+ {
+ if ( (*os == '\n') || (*os == '\r') )
+ width = max_width;
+ else
+ width--;
+ rtas_call(display_character, 1, 1, NULL, *os++ );
+ /* if we overwrite the screen length */
+ if ( width == 0 )
+ while ( (*os != 0) && (*os != '\n') && (*os != '\r') )
+ os++;
+ }
+
+ /* Blank to end of line. */
+ while ( width-- > 0 )
+ rtas_call(display_character, 1, 1, NULL, ' ' );
+}
+
+extern void setup_default_decr(void);
+
+extern unsigned long ppc_proc_freq;
+extern unsigned long ppc_tb_freq;
+
+void __init pSeries_calibrate_decr(void)
+{
+ struct device_node *cpu;
+ struct div_result divres;
+ int *fp;
+ unsigned long freq, processor_freq;
+
+ /*
+ * The cpu node should have a timebase-frequency property
+ * to tell us the rate at which the decrementer counts.
+ */
+ freq = 16666000; /* hardcoded default */
+ cpu = find_type_devices("cpu");
+ if (cpu != 0) {
+ fp = (int *) get_property(cpu, "timebase-frequency", NULL);
+ if (fp != 0)
+ freq = *fp;
+ }
+ ppc_tb_freq = freq;
+ processor_freq = freq;
+ if (cpu != 0) {
+ fp = (int *) get_property(cpu, "clock-frequency", NULL);
+ if (fp != 0)
+ processor_freq = *fp;
+ }
+ ppc_proc_freq = processor_freq;
+
+ printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ freq/1000000, freq%1000000 );
+ printk("time_init: processor frequency = %lu.%.6lu MHz\n",
+ processor_freq/1000000, processor_freq%1000000 );
+
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
+ tb_ticks_per_usec = freq / 1000000;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+ div128_by_32( 1024*1024, 0, tb_ticks_per_sec, &divres );
+ tb_to_xs = divres.result_low;
+
+ setup_default_decr();
+}
+
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/eeh.c linuxppc64_2_4/arch/ppc64/kernel/eeh.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/eeh.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/eeh.c Tue Nov 13 10:47:33 2001
@@ -0,0 +1,313 @@
+/*
+ * eeh.c
+ * Copyright (C) 2001 Dave Engebretsen & Todd Inglett 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:
+ * 2001/10/27 : engebret : Created.
+ * End Change Activity
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "pci.h"
+
+#define BUID_HI(buid) ((buid) >> 32)
+#define BUID_LO(buid) ((buid) & 0xffffffff)
+#define CONFIG_ADDR(busno, devfn) (((((busno) & 0xff) << 8) | ((devfn) & 0xf8)) << 8)
+
+unsigned long eeh_total_mmio_reads;
+unsigned long eeh_total_mmio_ffs;
+unsigned long eeh_false_positives;
+/* RTAS tokens */
+static int ibm_set_eeh_option;
+static int ibm_set_slot_reset;
+static int ibm_read_slot_reset_state;
+
+static int eeh_implemented;
+#define EEH_MAX_OPTS 4096
+static char *eeh_opts;
+static int eeh_opts_last;
+static int eeh_check_opts_config(struct pci_dev *dev);
+
+
+unsigned long eeh_token(unsigned long phb, unsigned long bus, unsigned long devfn, unsigned long offset)
+{
+ if (phb > 0xff)
+ panic("eeh_token: phb 0x%lx is too large\n", phb);
+ if (offset & 0x0fffffff00000000)
+ panic("eeh_token: offset 0x%lx is out of range\n", offset);
+ return ((IO_UNMAPPED_REGION_ID << 60) | (phb << 48UL) | ((bus & 0xff) << 40UL) | (devfn << 32UL) | (offset & 0xffffffff));
+}
+
+
+
+int eeh_get_state(unsigned long ea) {
+ return 0;
+}
+
+
+/* Check for an eeh failure at the given token address.
+ * The given value has been read and it should be 1's (0xff, 0xffff or 0xffffffff).
+ *
+ * Probe to determine if an error actually occurred. If not return val.
+ * Otherwise panic.
+ */
+unsigned long eeh_check_failure(void *token, unsigned long val)
+{
+ unsigned long config_addr = (unsigned long)token >> 24; /* PPBBDDRR */
+ unsigned long phbidx = (config_addr >> 24) & 0xff;
+ struct pci_controller *phb;
+ unsigned long ret, rets[2];
+
+ config_addr &= 0xffff00; /* 00BBDD00 */
+
+ if (phbidx >= global_phb_number) {
+ panic("EEH: checking token %p phb index of %ld is greater than max of %d\n", token, phbidx, global_phb_number-1);
+ }
+ phb = phbtab[phbidx];
+ eeh_false_positives++;
+
+ ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets,
+ config_addr, BUID_HI(phb->buid), BUID_LO(phb->buid));
+ if (ret == 0 && rets[1] == 1 && rets[2] != 0) {
+ struct pci_dev *dev;
+ int bus = ((unsigned long)token >> 40) & 0xffff; /* include PHB# in bus */
+ int devfn = (config_addr >> 8) & 0xff;
+
+ dev = pci_find_slot(bus, devfn);
+ if (dev)
+ panic("EEH: MMIO failure (%ld) on device:\n %s %s\n",
+ rets[2], dev->slot_name, dev->name);
+ else
+ panic("EEH: MMIO failure (%ld) on device buid %lx, config_addr %lx\n", rets[2], phb->buid, config_addr);
+ }
+ return val; /* good case */
+}
+
+void eeh_init(void) {
+ ibm_set_eeh_option = rtas_token("ibm,set-eeh-option");
+ ibm_set_slot_reset = rtas_token("ibm,set-slot-reset");
+ ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");
+ if (ibm_set_eeh_option != RTAS_UNKNOWN_SERVICE) {
+ printk("PCI Enhanced I/O Error Handling Enabled\n");
+ eeh_implemented = 1;
+ }
+}
+
+
+/* Given a PCI device check if eeh should be configured or not.
+ * This may look at firmware properties and/or kernel cmdline options.
+ */
+int is_eeh_configured(struct pci_dev *dev)
+{
+ struct device_node *dn = pci_device_to_OF_node(dev);
+ struct pci_controller *phb = PCI_GET_PHB_PTR(dev);
+ unsigned long ret, rets[2];
+
+ if (dn == NULL || phb == NULL || phb->buid == 0 || !eeh_implemented)
+ return 0;
+
+ /* Hack: turn off eeh for display class devices.
+ * This fixes matrox accel framebuffer.
+ */
+ if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
+ return 0;
+
+ if (!eeh_check_opts_config(dev))
+ return 0;
+
+ ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets,
+ CONFIG_ADDR(dn->busno, dn->devfn),
+ BUID_HI(phb->buid), BUID_LO(phb->buid));
+ if (ret == 0 && rets[1] == 1) {
+ printk("EEH: %s %s is EEH capable.\n", dev->slot_name, dev->name);
+ return 1;
+ }
+ return 0;
+}
+
+int eeh_set_option(struct pci_dev *dev, int option)
+{
+ struct device_node *dn = pci_device_to_OF_node(dev);
+ struct pci_controller *phb = PCI_GET_PHB_PTR(dev);
+
+ if (dn == NULL || phb == NULL || phb->buid == 0 || !eeh_implemented)
+ return -2;
+
+ return rtas_call(ibm_set_eeh_option, 4, 1, NULL,
+ CONFIG_ADDR(dn->busno, dn->devfn),
+ BUID_HI(phb->buid), BUID_LO(phb->buid), option);
+}
+
+
+static int eeh_proc_falsepositive_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+ len = sprintf(page, "eeh_false_positives=%ld\n"
+ "eeh_total_mmio_ffs=%ld\n"
+ "eeh_total_mmio_reads=%ld\n",
+ eeh_false_positives, eeh_total_mmio_ffs, eeh_total_mmio_reads);
+ return len;
+}
+
+/* Implementation of /proc/ppc64/eeh
+ * For now it is one file showing false positives.
+ */
+void eeh_init_proc(struct proc_dir_entry *top)
+{
+ struct proc_dir_entry *ent = create_proc_entry("eeh", S_IRUGO, top);
+ if (ent) {
+ ent->nlink = 1;
+ ent->data = NULL;
+ ent->read_proc = (void *)eeh_proc_falsepositive_read;
+ }
+}
+
+/*
+ * Test if "dev" should be configured on or off.
+ * This processes the options literally from right to left.
+ * This lets the user specify stupid combinations of options,
+ * but at least the result should be very predictable.
+ */
+static int eeh_check_opts_config(struct pci_dev *dev)
+{
+ struct device_node *dn = pci_device_to_OF_node(dev);
+ struct pci_controller *phb = PCI_GET_PHB_PTR(dev);
+ char devname[32], classname[32], phbname[32];
+ char *strs[8], *s;
+ int nstrs, i;
+ int ret = 0;
+
+ if (dn == NULL || phb == NULL || phb->buid == 0 || !eeh_implemented)
+ return 0;
+ /* Build list of strings to match */
+ nstrs = 0;
+ s = (char *)get_property(dn, "ibm,loc-code", 0);
+ if (s)
+ strs[nstrs++] = s;
+ sprintf(devname, "dev%04x:%04x", dev->vendor, dev->device);
+ strs[nstrs++] = devname;
+ sprintf(classname, "class%04x", dev->class);
+ strs[nstrs++] = classname;
+ sprintf(phbname, "pci@%lx", phb->buid);
+ strs[nstrs++] = phbname;
+ strs[nstrs++] = ""; /* yes, this matches the empty string */
+
+ /* Now see if any string matches the eeh_opts list.
+ * The eeh_opts list entries start with + or -.
+ */
+ for (s = eeh_opts; s && (s < (eeh_opts + eeh_opts_last)); s += strlen(s)+1) {
+ for (i = 0; i < nstrs; i++) {
+ if (strcasecmp(strs[i], s+1) == 0) {
+ ret = (strs[0] == '+') ? 1 : 0;
+ }
+ }
+ }
+ return ret;
+}
+
+/* Handle kernel eeh-on & eeh-off cmd line options for eeh.
+ *
+ * We support:
+ * eeh-off=loc1,loc2,loc3...
+ *
+ * and this option can be repeated so
+ * eeh-off=loc1,loc2 eeh=loc3
+ * is the same as eeh-off=loc1,loc2,loc3
+ *
+ * loc is an IBM location code that can be found in a manual or
+ * via openfirmware (or the Hardware Management Console).
+ *
+ * We also support these additional "loc" values:
+ *
+ * dev#:# vendor:device id in hex (e.g. dev1022:2000)
+ * class# class id in hex (e.g. class0200)
+ * pci@buid all devices under phb (e.g. pci@fef00000)
+ *
+ * If no location code is specified all devices are assumed
+ * so eeh-off means eeh by default is off.
+ */
+
+/* This is implemented as a null separated list of strings.
+ * Each string looks like this: "+X" or "-X"
+ * where X is a loc code, dev, class or pci string (as shown above)
+ * or empty which is used to indicate all.
+ *
+ * We interpret this option string list during the buswalk
+ * so that it will literally behave left-to-right even if
+ * some combinations don't make sense. Give the user exactly
+ * what they want! :)
+ */
+
+static int __init eeh_parm(char *str, int state)
+{
+ char *s, *cur, *curend;
+ if (!eeh_opts) {
+ eeh_opts = alloc_bootmem(EEH_MAX_OPTS);
+ eeh_opts[eeh_opts_last++] = '+'; /* default */
+ eeh_opts[eeh_opts_last++] = '\0';
+ }
+ if (*str == '\0') {
+ eeh_opts[eeh_opts_last++] = state ? '+' : '-';
+ eeh_opts[eeh_opts_last++] = '\0';
+ return 1;
+ }
+ if (*str == '=')
+ str++;
+ for (s = str; s && *s != '\0'; s = curend) {
+ cur = s;
+ while (*cur == ',')
+ cur++; /* ignore empties. Don't treat as "all-on" or "all-off" */
+ curend = strchr(cur, ',');
+ if (!curend)
+ curend = cur + strlen(cur);
+ if (*cur) {
+ int curlen = curend-cur;
+ char *sym = eeh_opts+eeh_opts_last;
+ if (eeh_opts_last + curlen > EEH_MAX_OPTS-2) {
+ printk("EEH: sorry...too many eeh cmd line options\n");
+ return 1;
+ }
+ eeh_opts[eeh_opts_last++] = state ? '+' : '-';
+ strncpy(eeh_opts+eeh_opts_last, cur, curlen);
+ eeh_opts_last += curlen;
+ eeh_opts[eeh_opts_last++] = '\0';
+ }
+ }
+ return 1;
+}
+
+static int __init eehoff_parm(char *str)
+{
+ return eeh_parm(str, 0);
+}
+static int __init eehon_parm(char *str)
+{
+ return eeh_parm(str, 1);
+}
+
+
+__setup("eeh-off", eehoff_parm);
+__setup("eeh-on", eehon_parm);
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/entry.S linuxppc64_2_4/arch/ppc64/kernel/entry.S
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/entry.S Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/entry.S Sat Feb 9 17:15:28 2002
@@ -0,0 +1,616 @@
+/*
+ * arch/ppc/kernel/entry.S
+ *
+ *
+ *
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
+ * Copyright (C) 1996 Cort Dougan
+ * Adapted for Power Macintosh by Paul Mackerras.
+ * Low-level exception handlers and MMU support
+ * rewritten by Paul Mackerras.
+ * Copyright (C) 1996 Paul Mackerras.
+ * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
+ *
+ * This file contains the system call entry code, context switch
+ * code, and exception/interrupt return code for PowerPC.
+ *
+ * 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.
+ *
+ */
+
+
+#include "ppc_asm.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef CONFIG_PPC_ISERIES
+#define DO_SOFT_DISABLE
+#endif
+
+#undef SHOW_SYSCALLS
+#undef SHOW_SYSCALLS_TASK
+
+#ifdef SHOW_SYSCALLS_TASK
+ .data
+show_syscalls_task:
+ .long -1
+#endif
+
+/*
+ * Handle a system call.
+ */
+ .text
+_GLOBAL(DoSyscall)
+ std r0,THREAD+LAST_SYSCALL(r13)
+ ld r11,_CCR(r1) /* Clear SO bit in CR */
+ lis r10,0x1000
+ andc r11,r11,r10
+ std r11,_CCR(r1)
+#ifdef SHOW_SYSCALLS
+#ifdef SHOW_SYSCALLS_TASK
+ LOADBASE(r31,show_syscalls_task)
+ ld r31,show_syscalls_task@l(r31)
+ cmp 0,r13,r31
+ bne 1f
+#endif
+ LOADADDR(r3,7f)
+ ld r4,GPR0(r1)
+ ld r5,GPR3(r1)
+ ld r6,GPR4(r1)
+ ld r7,GPR5(r1)
+ ld r8,GPR6(r1)
+ ld r9,GPR7(r1)
+ bl .printk
+ LOADADDR(r3,77f)
+ ld r4,GPR8(r1)
+ ld r5,GPR9(r1)
+ mr r6,r13
+ bl .printk
+ ld r0,GPR0(r1)
+ ld r3,GPR3(r1)
+ ld r4,GPR4(r1)
+ ld r5,GPR5(r1)
+ ld r6,GPR6(r1)
+ ld r7,GPR7(r1)
+ ld r8,GPR8(r1)
+1:
+#endif /* SHOW_SYSCALLS */
+ ld r10,TASK_PTRACE(r13)
+ andi. r10,r10,PT_TRACESYS
+ bne- 50f
+ cmpli 0,r0,NR_syscalls
+ bge- 66f
+/* Ken Aaker: Need to vector to 32 Bit or default sys_call_table here,
+ * based on caller's run-mode / personality.
+ *
+ */
+#ifdef CONFIG_BINFMT_ELF32
+ ld r10,THREAD+THREAD_FLAGS(r13)
+ andi. r10,r10,PPC_FLAG_32BIT
+ beq- 15f
+ LOADADDR(r10,.sys_call_table32)
+/* Now mung the first 4 parameters into shape, by making certain that
+ * the high bits (most significant 32 bits in 64 bit reg) are 0
+ * for the first 4 parameter regs(3-6).
+ */
+ clrldi r3,r3,32
+ clrldi r4,r4,32
+ clrldi r5,r5,32
+ clrldi r6,r6,32
+ b 17f
+15:
+#endif
+ LOADADDR(r10,.sys_call_table)
+17:
+ slwi r0,r0,3
+ ldx r10,r10,r0 /* Fetch system call handler [ptr] */
+ mtlr r10
+ addi r9,r1,STACK_FRAME_OVERHEAD
+ blrl /* Call handler */
+_GLOBAL(ret_from_syscall_1)
+20: std r3,RESULT(r1) /* Save result */
+#ifdef SHOW_SYSCALLS
+#ifdef SHOW_SYSCALLS_TASK
+ cmp 0,r13,r31
+ bne 91f
+#endif
+ mr r4,r3
+ LOADADDR(r3,79f)
+ bl .printk
+ ld r3,RESULT(r1)
+91:
+#endif
+ li r10,-_LAST_ERRNO
+ cmpl 0,r3,r10
+ blt 30f
+ neg r3,r3
+ cmpi 0,r3,ERESTARTNOHAND
+ bne 22f
+ li r3,EINTR
+22: ld r10,_CCR(r1) /* Set SO bit in CR */
+ oris r10,r10,0x1000
+ std r10,_CCR(r1)
+30: std r3,GPR3(r1) /* Update return value */
+ b .ret_from_except
+66: li r3,ENOSYS
+ b 22b
+
+/* Traced system call support */
+50: bl .syscall_trace
+ ld r0,GPR0(r1) /* Restore original registers */
+ ld r3,GPR3(r1)
+ ld r4,GPR4(r1)
+ ld r5,GPR5(r1)
+ ld r6,GPR6(r1)
+ ld r7,GPR7(r1)
+ ld r8,GPR8(r1)
+ ld r9,GPR9(r1)
+ cmpli 0,r0,NR_syscalls
+ bge- 66f
+#ifdef CONFIG_BINFMT_ELF32
+ ld r10,THREAD+THREAD_FLAGS(r13)
+ andi. r10,r10,PPC_FLAG_32BIT
+ beq- 55f
+ LOADADDR(r10,.sys_call_table32)
+/* Now mung the first 4 parameters into shape, by making certain that
+ * the high bits (most significant 32 bits in 64 bit reg) are 0
+ * for the first 4 parameter regs(3-6).
+ */
+ clrldi r3,r3,32
+ clrldi r4,r4,32
+ clrldi r5,r5,32
+ clrldi r6,r6,32
+ b 57f
+55:
+#endif
+ LOADADDR(r10,.sys_call_table)
+57:
+ slwi r0,r0,3
+ ldx r10,r10,r0 /* Fetch system call handler [ptr] */
+ mtlr r10
+ addi r9,r1,STACK_FRAME_OVERHEAD
+ blrl /* Call handler */
+_GLOBAL(ret_from_syscall_2)
+58: std r3,RESULT(r1) /* Save result */
+ std r3,GPR0(r1) /* temporary gross hack to make strace work */
+ li r10,-_LAST_ERRNO
+ cmpl 0,r3,r10
+ blt 60f
+ neg r3,r3
+ cmpi 0,r3,ERESTARTNOHAND
+ bne 57f
+ li r3,EINTR
+57: ld r10,_CCR(r1) /* Set SO bit in CR */
+ oris r10,r10,0x1000
+ std r10,_CCR(r1)
+60: std r3,GPR3(r1) /* Update return value */
+ bl .syscall_trace
+ b .ret_from_except
+66: li r3,ENOSYS
+ b 57b
+#ifdef SHOW_SYSCALLS
+7: .string "syscall %d(%x, %x, %x, %x, %x, "
+77: .string "%x, %x), current=%p\n"
+79: .string " -> %x\n"
+ .align 2,0
+#endif
+
+_GLOBAL(ppc32_sigreturn)
+ bl .sys32_sigreturn
+ b 80f
+
+_GLOBAL(ppc32_rt_sigreturn)
+ bl .sys32_rt_sigreturn
+ b 80f
+
+_GLOBAL(ppc64_sigreturn)
+ bl .sys_sigreturn
+ b 80f
+
+_GLOBAL(ppc64_rt_sigreturn)
+ bl .sys_rt_sigreturn
+
+80: ld r10,TASK_PTRACE(r13)
+ andi. r10,r10,PT_TRACESYS
+ bne- 81f
+ cmpi 0,r3,0
+ bge .ret_from_except
+ b 20b
+81: cmpi 0,r3,0
+ blt 58b
+ bl .syscall_trace
+ b .ret_from_except
+
+/*
+ * This routine switches between two different tasks. The process
+ * state of one is saved on its kernel stack. Then the state
+ * of the other is restored from its kernel stack. The memory
+ * management hardware is updated to the second process's state.
+ * Finally, we can return to the second process, via ret_from_except.
+ * On entry, r3 points to the THREAD for the current task, r4
+ * points to the THREAD for the new task.
+ *
+ * Note: there are two ways to get to the "going out" portion
+ * of this code; either by coming in via the entry (_switch)
+ * or via "fork" which must set up an environment equivalent
+ * to the "_switch" path. If you change this (or in particular, the
+ * SAVE_REGS macro), you'll have to change the fork code also.
+ *
+ * The code which creates the new task context is in 'copy_thread'
+ * in arch/ppc/kernel/process.c
+ */
+_GLOBAL(_switch)
+ stdu r1,-INT_FRAME_SIZE(r1)
+ ld r6,0(r1)
+ std r6,GPR1(r1)
+ /* r3-r13 are caller saved -- Cort */
+ SAVE_GPR(2, r1)
+ SAVE_8GPRS(14, r1)
+ SAVE_10GPRS(22, r1)
+ mflr r20 /* Return to switch caller */
+ mfmsr r22
+ li r6,MSR_FP /* Disable floating-point */
+ andc r22,r22,r6
+ mtmsrd r22
+ isync
+ std r20,_NIP(r1)
+ std r22,_MSR(r1)
+ std r20,_LINK(r1)
+ mfcr r20
+ std r20,_CCR(r1)
+ li r6,0x0ff0
+ std r6,TRAP(r1)
+ std r1,KSP(r3) /* Set old stack pointer */
+
+ mfspr r5,SPRG3 /* Get Paca */
+ addi r3,r3,-THREAD /* old 'current' for return value */
+ addi r13,r4,-THREAD /* Convert THREAD to 'current' */
+ std r13,PACACURRENT(r5) /* Set new 'current' */
+
+#ifdef CONFIG_PPC_ISERIES
+ ld r7,THREAD_FLAGS(r4) /* Get run light flag */
+ mfspr r9,CTRLF
+ srdi r7,r7,1 /* Align to run light bit in CTRL reg */
+ insrdi r9,r7,1,63 /* Insert run light into CTRL */
+ mtspr CTRLT,r9
+#endif
+ ld r1,KSP(r4) /* Load new stack pointer */
+ ld r6,_CCR(r1)
+ mtcrf 0xFF,r6
+ /* r3-r13 are destroyed -- Cort */
+ REST_8GPRS(14, r1)
+ REST_10GPRS(22, r1)
+
+ ld r7,_NIP(r1) /* Return to _switch caller in new task */
+ ld r1,GPR1(r1)
+ mtlr r7
+ blr
+
+_GLOBAL(ret_from_fork)
+ bl .schedule_tail
+ ld r0,TASK_PTRACE(r13)
+ andi. r0,r0,PT_TRACESYS
+ beq+ .ret_from_except
+ bl .syscall_trace
+ b .ret_from_except
+
+_GLOBAL(ret_from_except)
+#ifdef CONFIG_PPC_ISERIES
+ ld r5,SOFTE(r1)
+ cmpdi 0,r5,0
+ beq 4f
+irq_recheck:
+ /*
+ * Check for pending interrupts (iSeries)
+ */
+ CHECKANYINT(r3,r4)
+ beq+ 4f /* skip do_IRQ if no interrupts */
+
+ mfspr r5,SPRG3
+ li r3,0
+ stb r3,PACAPROCENABLED(r5) /* ensure we are disabled */
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl .do_IRQ
+ b irq_recheck /* loop back and handle more */
+4:
+#endif
+_GLOBAL(do_bottom_half_ret)
+ ld r3,_MSR(r1) /* Returning to user mode? */
+ andi. r3,r3,MSR_PR
+ beq+ restore /* if so, check need_resched and signals */
+_GLOBAL(ret_to_user_hook)
+ nop
+ /* NEED_RESCHED is a volatile long (64-bits) */
+ ld r3,NEED_RESCHED(r13)
+ cmpi 0,r3,0 /* check need_resched flag */
+ beq+ 7f
+ bl .schedule
+ /* SIGPENDING is an int (32-bits) */
+7:
+ lwz r5,SIGPENDING(r13) /* Check for pending unblocked signals */
+ cmpwi 0,r5,0
+ beq+ restore
+ li r3,0
+ addi r4,r1,STACK_FRAME_OVERHEAD
+ bl .do_signal
+_GLOBAL(do_signal_ret)
+restore:
+ ld r3,_CTR(r1)
+ ld r0,_LINK(r1)
+ mtctr r3
+ mtlr r0
+ ld r3,_XER(r1)
+ mtspr XER,r3
+ REST_8GPRS(5, r1)
+ REST_10GPRS(14, r1)
+ REST_8GPRS(24, r1)
+
+ /* make sure we hard disable here, even if rtl is active, to protect
+ * SRR[01] and SPRG2 -- Cort
+ */
+ mfmsr r0 /* Get current interrupt state */
+ li r4,0
+ ori r4,r4,MSR_EE|MSR_RI
+ andc r0,r0,r4 /* clear MSR_EE and MSR_RI */
+ mtmsrd r0 /* Update machine state */
+#ifdef CONFIG_PPC_ISERIES
+ ld r0,SOFTE(r1)
+ cmpi 0,r0,0
+ beq+ 1f
+
+ CHECKANYINT(r4,r3)
+ beq+ 1f
+ mfmsr r0
+ ori r0,r0,MSR_EE|MSR_RI
+ mtmsrd r0
+ b irq_recheck
+
+1:
+#endif
+ stdcx. r0,0,r1 /* to clear the reservation */
+
+ mfspr r4,SPRG3 /* current task's PACA */
+#ifdef DO_SOFT_DISABLE
+ ld r0,SOFTE(r1)
+ stb r0,PACAPROCENABLED(r4)
+#endif
+ /* 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 */
+ std r0,THREAD+KSP(r13) /* save kernel stack pointer */
+ std r1,PACAKSAVE(r4) /* save exception stack pointer */
+1:
+ ld r0,_MSR(r1)
+ mtspr SRR1,r0
+ ld r2,_CCR(r1)
+ mtcrf 0xFF,r2
+ ld r2,_NIP(r1)
+ mtspr SRR0,r2
+ REST_GPR(13,r1)
+ ld r0,GPR0(r1)
+ ld r2,GPR2(r1)
+ ld r3,GPR3(r1)
+ ld r4,GPR4(r1)
+ ld r1,GPR1(r1)
+
+ rfid
+
+/*
+ * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
+ * called with the MMU off.
+ *
+ * In addition, we need to be in 32b mode, at least for now.
+ *
+ * Note: r3 is an input parameter to rtas, so don't trash it...
+ */
+_GLOBAL(enter_rtas)
+ mflr r0
+ std r0,16(r1)
+ stdu r1,-RTAS_FRAME_SIZE(r1) /* Save SP and create stack space. */
+
+ /* Because RTAS is running in 32b mode, it clobbers the high order half
+ * of all registers that it saves. We therefore save those registers
+ * RTAS might touch to the stack. (r0, r3-r13 are caller saved)
+ */
+ SAVE_GPR(2, r1) /* Save the TOC */
+ SAVE_GPR(13, r1) /* Save current */
+ SAVE_8GPRS(14, r1) /* Save the non-volatiles */
+ SAVE_10GPRS(22, r1) /* ditto */
+
+ mfcr r4
+ std r4,_CCR(r1)
+ mfctr r5
+ std r5,_CTR(r1)
+ mfspr r6,XER
+ std r6,_XER(r1)
+ mfdar r7
+ std r7,_DAR(r1)
+ mfdsisr r8
+ std r8,_DSISR(r1)
+ mfsrr0 r9
+ std r9,_SRR0(r1)
+ mfsrr1 r10
+ std r10,_SRR1(r1)
+
+ /* Unfortunatly, the stack pointer and the MSR are also clobbered,
+ * so they are saved in the PACA (SPRG3) which allows us to restore
+ * our original state after RTAS returns.
+ */
+ mfspr r4,SPRG3 /* Get PACA */
+ std r1,PACAR1(r4)
+ mfmsr r6
+ std r6,PACASAVEDMSR(r4)
+
+ /* Setup our real return addr */
+ SET_REG_TO_LABEL(r4,.rtas_return_loc)
+ SET_REG_TO_CONST(r9,KERNELBASE)
+ sub r4,r4,r9
+ mtlr r4
+
+ li r0,0
+ ori r0,r0,MSR_EE|MSR_SE|MSR_BE|MSR_RI
+ andc r0,r6,r0
+
+ li r9,1
+ rldicr r9,r9,MSR_SF_LG,(63-MSR_SF_LG)
+ ori r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP|MSR_RI
+ andc r6,r0,r9
+ sync /* disable interrupts so SRR0/1 */
+ mtmsrd r0 /* don't get trashed */
+
+ SET_REG_TO_LABEL(r4,rtas)
+ ld r5,RTASENTRY(r4) /* get the rtas->entry value */
+ ld r4,RTASBASE(r4) /* get the rtas->base value */
+
+ mtspr SRR0,r5
+ mtspr SRR1,r6
+ rfid
+
+_STATIC(rtas_return_loc)
+ /* relocation is off at this point */
+ mfspr r4,SPRG3 /* Get PACA */
+ SET_REG_TO_CONST(r5, KERNELBASE)
+ sub r4,r4,r5 /* RELOC the PACA base pointer */
+
+ ld r1,PACAR1(r4) /* Restore our SP */
+ LOADADDR(r3,.rtas_restore_regs)
+ ld r4,PACASAVEDMSR(r4) /* Restore our MSR */
+
+ mtspr SRR0,r3
+ mtspr SRR1,r4
+ rfid
+
+_STATIC(rtas_restore_regs)
+ /* relocation is on at this point */
+ REST_GPR(2, r1) /* Restore the TOC */
+ REST_GPR(13, r1) /* Restore current */
+ REST_8GPRS(14, r1) /* Restore the non-volatiles */
+ REST_10GPRS(22, r1) /* ditto */
+
+ /* put back current in r13 */
+ mfspr r4,SPRG3
+ ld r13,PACACURRENT(r4)
+
+ ld r4,_CCR(r1)
+ mtcr r4
+ ld r5,_CTR(r1)
+ mtctr r5
+ ld r6,_XER(r1)
+ mtspr XER,r6
+ ld r7,_DAR(r1)
+ mtdar r7
+ ld r8,_DSISR(r1)
+ mtdsisr r8
+ ld r9,_SRR0(r1)
+ mtsrr0 r9
+ ld r10,_SRR1(r1)
+ mtsrr1 r10
+
+ addi r1,r1,RTAS_FRAME_SIZE /* Unstack our frame */
+ ld r0,16(r1) /* get return address */
+
+ mtlr r0
+ blr /* return to caller */
+
+
+_GLOBAL(enter_prom)
+ mflr r0
+ std r0,16(r1)
+ stdu r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
+
+ /* Because PROM is running in 32b mode, it clobbers the high order half
+ * of all registers that it saves. We therefore save those registers
+ * PROM might touch to the stack. (r0, r3-r13 are caller saved)
+ */
+ SAVE_8GPRS(2, r1) /* Save the TOC & incoming param(s) */
+ SAVE_GPR(13, r1) /* Save current */
+ SAVE_8GPRS(14, r1) /* Save the non-volatiles */
+ SAVE_10GPRS(22, r1) /* ditto */
+
+ mfcr r4
+ std r4,_CCR(r1)
+ mfctr r5
+ std r5,_CTR(r1)
+ mfspr r6,XER
+ std r6,_XER(r1)
+ mfdar r7
+ std r7,_DAR(r1)
+ mfdsisr r8
+ std r8,_DSISR(r1)
+ mfsrr0 r9
+ std r9,_SRR0(r1)
+ mfsrr1 r10
+ std r10,_SRR1(r1)
+ mfmsr r11
+ std r11,_MSR(r1)
+
+ /* Unfortunatly, the stack pointer is also clobbered, so it is saved
+ * in the SPRG2 which allows us to restore our original state after
+ * PROM returns.
+ */
+ mtspr SPRG2,r1
+
+ /* put a relocation offset into r3 */
+ bl .reloc_offset
+ LOADADDR(r12,prom)
+ sub r12,r12,r3
+ ld r12,PROMENTRY(r12) /* get the prom->entry value */
+ mtlr r12
+
+ mfmsr r11 /* grab the current MSR */
+ li r12,1
+ rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
+ andc r11,r11,r12
+ li r12,1
+ rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
+ andc r11,r11,r12
+ mtmsrd r11
+ isync
+
+ REST_8GPRS(2, r1) /* Restore the TOC & param(s) */
+ REST_GPR(13, r1) /* Restore current */
+ REST_8GPRS(14, r1) /* Restore the non-volatiles */
+ REST_10GPRS(22, r1) /* ditto */
+ blrl /* Entering PROM here... */
+
+ mfspr r1,SPRG2 /* Restore the stack pointer */
+ ld r6,_MSR(r1) /* Restore the MSR */
+ mtmsrd r6
+ isync
+
+ REST_GPR(2, r1) /* Restore the TOC */
+ REST_GPR(13, r1) /* Restore current */
+ REST_8GPRS(14, r1) /* Restore the non-volatiles */
+ REST_10GPRS(22, r1) /* ditto */
+
+ ld r4,_CCR(r1)
+ mtcr r4
+ ld r5,_CTR(r1)
+ mtctr r5
+ ld r6,_XER(r1)
+ mtspr XER,r6
+ ld r7,_DAR(r1)
+ mtdar r7
+ ld r8,_DSISR(r1)
+ mtdsisr r8
+ ld r9,_SRR0(r1)
+ mtsrr0 r9
+ ld r10,_SRR1(r1)
+ mtsrr1 r10
+ addi r1,r1,PROM_FRAME_SIZE
+ ld r0,16(r1) /* get return address */
+
+ mtlr r0
+ blr /* return to caller */
+
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/flight_recorder.c linuxppc64_2_4/arch/ppc64/kernel/flight_recorder.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/flight_recorder.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/flight_recorder.c Tue Dec 18 01:09:09 2001
@@ -0,0 +1,182 @@
+/************************************************************************
+ * flight_recorder.c
+ ************************************************************************
+ * This code supports the a generic flight recorder. *
+ * 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 *
+ ************************************************************************
+ * This is a simple text based flight recorder. Useful for logging
+ * information the you may want to retreive at a latter time. Errors or
+ * debug inforamtion are good examples. A good method to dump the
+ * information is via the proc file system.
+ *
+ * To use.
+ * 1. Create the flight recorder object. Passing a NULL pointer will
+ * kmalloc the space for you. If it is too early for kmalloc, create
+ * space for the object. Beware, don't lie about the size, you will
+ * pay for that later.
+ * FlightRecorder* TestFr = alloc_Flight_Recorder(NULL,"TestFr",4096);
+ *
+ * 2. Log any notable events, initialzation, error conditions, etc.
+ * LOGFR(TestFr,"5. Stack Variable(10) %d",StackVariable);
+ *
+ * 3. Dump the information to a buffer.
+ * fr_Dump(TestFr, proc_file_buffer, proc_file_buffer_size);
+ *
+ ************************************************************************/
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static char LogText[512];
+static int LogTextIndex;
+static int LogCount = 0;
+static spinlock_t Fr_Lock;
+
+/************************************************************************
+ * Build the log time prefix based on Flags.
+ * 00 = No time prefix
+ * 01 = Date(mmddyy) Time(hhmmss) prefix
+ * 02 = Day(dd) Time(hhmmss) prefix
+ * 03 = Time(hhmmss) prefix
+ ************************************************************************/
+static void fr_Log_Time(FlightRecorder* Fr)
+{
+ struct timeval TimeClock;
+ struct rtc_time LogTime;
+
+ do_gettimeofday(&TimeClock);
+ to_tm(TimeClock.tv_sec, &LogTime);
+
+ if (Fr->Flags == 1) {
+ LogTextIndex = sprintf(LogText,"%02d%02d%02d %02d%02d%02d ",
+ LogTime.tm_mon, LogTime.tm_mday, LogTime.tm_year-2000,
+ LogTime.tm_hour,LogTime.tm_min, LogTime.tm_sec);
+ }
+ else if (Fr->Flags == 2) {
+ LogTextIndex = sprintf(LogText,"%02d %02d%02d%02d ",
+ LogTime.tm_mday,
+ LogTime.tm_hour,LogTime.tm_min, LogTime.tm_sec);
+ }
+
+ else if (Fr->Flags == 3) {
+ LogTextIndex = sprintf(LogText,"%02d%02d%02d ",
+ LogTime.tm_hour,LogTime.tm_min, LogTime.tm_sec);
+ }
+ else {
+ ++LogCount;
+ LogTextIndex = sprintf(LogText,"%04d. ",LogCount);
+ }
+}
+
+/************************************************************************/
+/* Log entry into buffer, */
+/* ->If entry is going to wrap, log "WRAP" and start at the top. */
+/************************************************************************/
+static void fr_Log_Data(FlightRecorder* Fr)
+{
+ int TextLen = strlen(LogText);
+ int Residual = ( Fr->EndPointer - Fr->NextPointer)-15;
+ if (TextLen > Residual) {
+ strcpy(Fr->NextPointer,"WRAP");
+ Fr->WrapPointer = Fr->NextPointer + 5;
+ Fr->NextPointer = Fr->StartPointer;
+ }
+ strcpy(Fr->NextPointer,LogText);
+ Fr->NextPointer += TextLen+1;
+ strcpy(Fr->NextPointer,"<=");
+}
+/************************************************************************
+ * Build the log text, support variable args.
+ ************************************************************************/
+void fr_Log_Entry(struct flightRecorder* LogFr, const char *fmt, ...)
+{
+ va_list arg_ptr;
+ spin_lock(&Fr_Lock);
+
+ fr_Log_Time(LogFr);
+ va_start(arg_ptr, fmt);
+ vsprintf(LogText+LogTextIndex, fmt, arg_ptr);
+ va_end(arg_ptr);
+ fr_Log_Data(LogFr);
+
+ spin_unlock(&Fr_Lock);
+
+}
+/************************************************************************
+ * Dump Flight Recorder into buffer.
+ * -> Handles the buffer wrapping.
+ ************************************************************************/
+int fr_Dump(FlightRecorder* Fr, char *Buffer, int BufferLen)
+{
+ int LineLen = 0;
+ char* StartEntry;
+ char* EndEntry;
+ spin_lock(&Fr_Lock);
+ /****************************************************************
+ * If Buffer has wrapped, find last usable entry to start with.
+ ****************************************************************/
+ if (Fr->WrapPointer != NULL) {
+ StartEntry = Fr->NextPointer+3;
+ StartEntry += strlen(StartEntry)+1;
+ EndEntry = Fr->WrapPointer;
+
+ while (EndEntry > StartEntry && LineLen < BufferLen) {
+ LineLen += sprintf(Buffer+LineLen,"%s\n",StartEntry);
+ StartEntry += strlen(StartEntry) + 1;
+ }
+ }
+
+ /****************************************************************
+ * Dump from the beginning to the last logged entry
+ ****************************************************************/
+ StartEntry = Fr->StartPointer;
+ EndEntry = Fr->NextPointer;
+ while (EndEntry > StartEntry && LineLen < BufferLen) {
+ LineLen += sprintf(Buffer+LineLen,"%s\n",StartEntry);
+ StartEntry += strlen(StartEntry) + 1;
+ }
+ spin_unlock(&Fr_Lock);
+ return LineLen;
+}
+
+/************************************************************************
+ * Allocate and Initialized the Flight Recorder
+ * -> If no FlightRecorder pointer is passed, the space is kmalloc.
+ ************************************************************************/
+FlightRecorder* alloc_Flight_Recorder(FlightRecorder* FrPtr, char* Signature, int SizeOfFr)
+{
+ FlightRecorder* Fr = FrPtr; /* Pointer to Object */
+ int FrSize = (SizeOfFr/16)*16; /* Could be static */
+ if (Fr == NULL)
+ Fr = (FlightRecorder*)kmalloc(SizeOfFr, GFP_KERNEL);
+ memset(Fr,0,SizeOfFr);
+ strcpy(Fr->Signature,Signature);
+ Fr->Size = FrSize;
+ Fr->Flags = 0;
+ Fr->StartPointer = (char*)&Fr->Buffer;
+ Fr->EndPointer = (char*)Fr + Fr->Size;
+ Fr->NextPointer = Fr->StartPointer;
+
+ fr_Log_Entry(Fr,"Initialized.");
+ return Fr;
+}
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/head.S linuxppc64_2_4/arch/ppc64/kernel/head.S
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/head.S Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/head.S Thu Nov 8 23:13:41 2001
@@ -0,0 +1,1849 @@
+/*
+ * arch/ppc64/kernel/head.S
+ *
+ *
+ *
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
+ * Copyright (C) 1996 Cort Dougan
+ * Adapted for Power Macintosh by Paul Mackerras.
+ * Low-level exception handlers and MMU support
+ * rewritten by Paul Mackerras.
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and
+ * Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com
+ *
+ * This file contains the low-level support and setup for the
+ * PowerPC-64 platform, including trap and interrupt dispatch.
+ *
+ * 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.
+ *
+ */
+
+#define SECONDARY_PROCESSORS
+
+#include "ppc_asm.h"
+#include "ppc_defs.h"
+#include
+#include
+#include
+#include
+
+#ifdef CONFIG_PPC_ISERIES
+#define DO_SOFT_DISABLE
+#endif
+
+/*
+ * We layout physical memory as follows:
+ * 0x0000 - 0x00ff : Secondary processor spin code
+ * 0x0100 - 0x2fff : pSeries Interrupt prologs
+ * 0x3000 - 0x3fff : Interrupt support
+ * 0x4000 - 0x4fff : NACA
+ * 0x5000 - 0x5fff : Initial segment table
+ * 0x6000 : iSeries and common interrupt prologs
+ *
+ */
+
+/*
+ * SPRG Usage
+ *
+ * Register Definition
+ *
+ * SPRG0 reserved for hypervisor
+ * SPRG1 temp - used to save gpr
+ * SPRG2 temp - used to save gpr
+ * SPRG3 virt addr of Paca
+ */
+
+/*
+ * Entering into this code we make the following assumptions:
+ * For pSeries:
+ * 1. The MMU is off & open firmware is running in real mode.
+ * 2. The kernel is entered at __start
+ *
+ * For iSeries:
+ * 1. The MMU is on (as it always is for iSeries)
+ * 2. The kernel is entered at SystemReset_Iseries
+ */
+
+ .text
+ .globl _stext
+_stext:
+_STATIC(__start)
+ b .__start_initialization_pSeries
+
+ /* At offset 0x20, there is a pointer to iSeries LPAR data.
+ * This is required by the hypervisor */
+ . = 0x20
+ .llong hvReleaseData-KERNELBASE
+
+ /* At offset 0x28 and 0x30 are offsets to the msChunks
+ * array (used by the iSeries LPAR debugger to do translation
+ * between physical addresses and absolute addresses) and
+ * to the pidhash table (also used by the debugger) */
+ .llong msChunks-KERNELBASE
+ .llong pidhash-KERNELBASE
+
+ /* Offset 0x38 - Pointer to start of embedded System.map */
+ .globl embedded_sysmap_start
+embedded_sysmap_start:
+ .llong 0
+ /* Offset 0x40 - Pointer to end of embedded System.map */
+ .globl embedded_sysmap_end
+embedded_sysmap_end:
+ .llong 0
+
+ /* Secondary processors spin on this value until it goes to 1. */
+ .globl __secondary_hold_spinloop
+__secondary_hold_spinloop:
+ .llong 0x0
+
+ /* Secondary processors write this value with their cpu # */
+ /* after they enter the spin loop immediatly below. */
+ .globl __secondary_hold_acknowledge
+__secondary_hold_acknowledge:
+ .llong 0x0
+
+ . = 0x60
+/*
+ * The following code is used on pSeries to hold secondary processors
+ * in a spin loop after they have been freed from OpenFirmware, but
+ * before the bulk of the kernel has been relocated. This code
+ * is relocated to physical address 0x60 before prom_init is run.
+ * All of it must fit below the first exception vector at 0x100.
+ */
+_GLOBAL(__secondary_hold)
+ /* Grab our linux cpu number */
+ mr r24,r3
+
+ /* Tell the master cpu we're here */
+ /* Relocation is off & we are located at an address less */
+ /* than 0x100, so only need to grab low order offset. */
+ std r24,__secondary_hold_acknowledge@l(0)
+
+ /* All secondary cpu's wait here until told to start. */
+100: ld r4,__secondary_hold_spinloop@l(0)
+ cmpdi 0,r4,1
+ bne 100b
+
+#ifdef CONFIG_HMT
+ b .hmt_init
+#else
+#ifdef CONFIG_SMP
+ mr r3,r24
+ b .pseries_secondary_smp_init
+#else
+ BUG_OPCODE
+#endif
+#endif
+
+/*
+ * The following macros define the code that appears as
+ * the prologue to each of the exception handlers. They
+ * are split into two parts to allow a single kernel binary
+ * to be used for pSeries, and iSeries.
+ */
+
+/*
+ * We make as much of the exception code common between native Pseries
+ * and Iseries LPAR implementations as possible.
+ */
+
+/*
+ * This is the start of the interrupt handlers for Pseries
+ * This code runs with relocation off.
+ */
+#define EX_SRR0 0
+#define EX_SRR1 8
+#define EX_R20 16
+#define EX_R21 24
+#define EX_R22 32
+#define EX_R23 40
+#define EX_DAR 48
+#define EX_DSISR 56
+
+#define EXCEPTION_PROLOG_PSERIES(label) \
+ mtspr SPRG2,r20; /* use SPRG2 as scratch reg */ \
+ mtspr SPRG1,r21; /* save r21 */ \
+ mfspr r20,SPRG3; /* get Paca virt addr */ \
+ ld r21,PACAEXCSP(r20); /* get exception stack ptr */ \
+ addi r21,r21,EXC_FRAME_SIZE; /* make exception frame */ \
+ std r22,EX_R22(r21); /* Save r22 in exc. frame */ \
+ std r23,EX_R23(r21); /* Save r23 in exc. frame */ \
+ mfspr r22,SRR0; /* EA of interrupted instr */ \
+ std r22,EX_SRR0(r21); /* Save SRR0 in exc. frame */ \
+ mfspr r23,SRR1; /* machine state at interrupt */ \
+ std r23,EX_SRR1(r21); /* Save SRR1 in exc. frame */ \
+ clrrdi r22,r20,60; /* Get 0xc part of the vaddr */ \
+ ori r22,r22,(label)@l; /* add in the vaddr offset */ \
+ /* assumes *_common < 16b */ \
+ mfmsr r23; \
+ rotldi r23,r23,4; \
+ ori r23,r23,0x30B; /* Set IR, DR, SF, ISF, HV */ \
+ rotldi r23,r23,60; /* for generic handlers */ \
+ mtspr SRR0,r22; \
+ mtspr SRR1,r23; \
+ mfcr r23; /* save CR in r23 */ \
+ rfid
+
+/*
+ * This is the start of the interrupt handlers for i_series
+ * This code runs with relocation on.
+ */
+#define EXCEPTION_PROLOG_ISERIES \
+ mtspr SPRG2,r20; /* use SPRG2 as scratch reg */\
+ mtspr SPRG1,r21; /* save r21 */\
+ mfspr r20,SPRG3; /* get Paca */\
+ ld r21,PACAEXCSP(r20); /* get exception stack ptr */\
+ addi r21,r21,EXC_FRAME_SIZE; /* make exception frame */\
+ std r22,EX_R22(r21); /* save r22 on exception frame */\
+ std r23,EX_R23(r21); /* Save r23 in exc. frame */\
+ ld r22,LPPACA+LPPACASRR0(r20); /* Get SRR0 from ItLpPaca */\
+ std r22,EX_SRR0(r21); /* save SRR0 in exc. frame */\
+ ld r23,LPPACA+LPPACASRR1(r20); /* Get SRR1 from ItLpPaca */\
+ std r23,EX_SRR1(r21); /* save SRR1 in exc. frame */\
+ mfcr r23; /* save CR in r23 */
+
+/*
+ * The common exception prolog is used for all except a few exceptions
+ * such as a segment miss on a kernel address. We have to be prepared
+ * to take another exception from the point where we first touch the
+ * kernel stack onwards.
+ *
+ * On entry r20 points to the paca and r21 points to the exception
+ * frame on entry, r23 contains the saved CR, and relocation is on.
+ */
+#define EXCEPTION_PROLOG_COMMON \
+ mfspr r22,SPRG2; /* Save r20 in exc. frame */ \
+ std r22,EX_R20(r21); \
+ mfspr r22,SPRG1; /* Save r21 in exc. frame */ \
+ std r22,EX_R21(r21); \
+ mfspr r22,DAR; /* Save DAR in exc. frame */ \
+ std r22,EX_DAR(r21); \
+ std r21,PACAEXCSP(r20); /* update exception stack ptr */ \
+ /* iff no protection flt */ \
+ mfspr r22,DSISR; /* Save DSISR in exc. frame */ \
+ std r22,EX_DSISR(r21); \
+ ld r22,EX_SRR1(r21); /* Get SRR1 from exc. frame */ \
+ andi. r22,r22,MSR_PR; /* Set CR for later branch */ \
+ mr r22,r1; /* Save r1 */ \
+ subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */ \
+ beq- 1f; \
+ ld r1,PACAKSAVE(r20); /* kernel stack to use */ \
+1: std r22,GPR1(r1); /* save r1 in stackframe */ \
+ std r22,0(r1); /* make stack chain pointer */ \
+ std r23,_CCR(r1); /* save CR in stackframe */ \
+ ld r22,EX_R20(r21); /* move r20 to stackframe */ \
+ std r22,GPR20(r1); \
+ ld r23,EX_R21(r21); /* move r21 to stackframe */ \
+ std r23,GPR21(r1); \
+ ld r22,EX_R22(r21); /* move r22 to stackframe */ \
+ std r22,GPR22(r1); \
+ ld r23,EX_R23(r21); /* move r23 to stackframe */ \
+ std r23,GPR23(r1); \
+ mflr r22; /* save LR in stackframe */ \
+ std r22,_LINK(r1); \
+ mfctr r23; /* save CTR in stackframe */ \
+ std r23,_CTR(r1); \
+ mfspr r22,XER; /* save XER in stackframe */ \
+ std r22,_XER(r1); \
+ ld r23,EX_DAR(r21); /* move DAR to stackframe */ \
+ std r23,_DAR(r1); \
+ ld r22,EX_DSISR(r21); /* move DSISR to stackframe */ \
+ std r22,_DSISR(r1); \
+ lbz r22,PACAPROCENABLED(r20); \
+ std r22,SOFTE(r1); \
+ ld r22,EX_SRR0(r21); /* get SRR0 from exc. frame */ \
+ ld r23,EX_SRR1(r21); /* get SRR1 from exc. frame */ \
+ addi r21,r21,-EXC_FRAME_SIZE;/* pop off exception frame */ \
+ std r21,PACAEXCSP(r20); \
+ SAVE_GPR(0, r1); /* save r0 in stackframe */ \
+ SAVE_8GPRS(2, r1); /* save r2 - r13 in stackframe */ \
+ SAVE_4GPRS(10, r1); \
+ ld r2,PACATOC(r20); \
+ ld r13,PACACURRENT(r20)
+
+/*
+ * Note: code which follows this uses cr0.eq (set if from kernel),
+ * r1, r22 (SRR0), and r23 (SRR1).
+ */
+
+/*
+ * Exception vectors.
+ */
+#define STD_EXCEPTION_PSERIES(n, label ) \
+ . = n; \
+ .globl label##_Pseries; \
+label##_Pseries: \
+ EXCEPTION_PROLOG_PSERIES( label##_common )
+
+#define STD_EXCEPTION_ISERIES( label ) \
+ .globl label##_Iseries; \
+label##_Iseries: \
+ EXCEPTION_PROLOG_ISERIES; \
+ b label##_common
+
+#define MASKABLE_EXCEPTION_ISERIES( label ) \
+ .globl label##_Iseries; \
+label##_Iseries: \
+ EXCEPTION_PROLOG_ISERIES; \
+ lbz r22,PACAPROFENABLED(r20); \
+ cmpi 0,r22,0; \
+ bne- label##_Iseries_profile; \
+label##_Iseries_prof_ret: \
+ lbz r22,PACAPROCENABLED(r20); \
+ cmpi 0,r22,0; \
+ beq- label##_Iseries_masked; \
+ b label##_common; \
+label##_Iseries_profile: \
+ std r24,48(r21); \
+ std r25,56(r21); \
+ mflr r24; \
+ bl do_profile; \
+ mtlr r24; \
+ ld r24,48(r21); \
+ ld r25,56(r21); \
+ b label##_Iseries_prof_ret
+
+#define STD_EXCEPTION_COMMON( trap, label, hdlr ) \
+ .globl label##_common; \
+label##_common: \
+ EXCEPTION_PROLOG_COMMON; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ li r20,0; \
+ li r6,trap; \
+ bl .save_remaining_regs; \
+ bl hdlr; \
+ b .ret_from_except
+
+/*
+ * Start of pSeries system interrupt routines
+ */
+ . = 0x100
+ .globl __start_interupts
+__start_interupts:
+
+ STD_EXCEPTION_PSERIES( 0x100, SystemReset )
+ STD_EXCEPTION_PSERIES( 0x200, MachineCheck )
+ STD_EXCEPTION_PSERIES( 0x300, DataAccess )
+ STD_EXCEPTION_PSERIES( 0x380, DataAccessSLB )
+ STD_EXCEPTION_PSERIES( 0x400, InstructionAccess )
+ STD_EXCEPTION_PSERIES( 0x480, InstructionAccessSLB )
+ STD_EXCEPTION_PSERIES( 0x500, HardwareInterrupt )
+ STD_EXCEPTION_PSERIES( 0x600, Alignment )
+ STD_EXCEPTION_PSERIES( 0x700, ProgramCheck )
+ STD_EXCEPTION_PSERIES( 0x800, FPUnavailable )
+ STD_EXCEPTION_PSERIES( 0x900, Decrementer )
+ STD_EXCEPTION_PSERIES( 0xa00, Trap_0a )
+ STD_EXCEPTION_PSERIES( 0xb00, Trap_0b )
+ STD_EXCEPTION_PSERIES( 0xc00, SystemCall )
+ STD_EXCEPTION_PSERIES( 0xd00, SingleStep )
+ STD_EXCEPTION_PSERIES( 0xe00, Trap_0e )
+ STD_EXCEPTION_PSERIES( 0xf00, PerformanceMonitor )
+ STD_EXCEPTION_PSERIES( 0x1300, InstructionBreakpoint )
+
+ . = 0x4000
+ .globl __end_interupts
+ .globl __start_naca
+__end_interupts:
+__start_naca:
+ /* Save space for naca.
+ * The first dword of the Naca is required by iSeries LPAR to
+ * point to itVpdAreas. On pSeries native, this value is not used.
+ */
+ .llong itVpdAreas
+ .llong 0x0
+ .llong 0x0
+ .llong xPaca
+
+ /*
+ * Space for the initial segment table
+ * For LPAR, the hypervisor must fill in at least one entry
+ * before we get control (with relocate on)
+ */
+
+ . = 0x5000
+ .globl __end_naca
+ .globl __start_stab
+__end_naca:
+__start_stab:
+
+
+ . = 0x6000
+ .globl __end_stab
+__end_stab:
+
+ /*
+ * The iSeries LPAR map is at this fixed address
+ * so that the HvReleaseData structure can address
+ * it with a 32-bit offset.
+ *
+ * The VSID values below are dependent on the
+ * VSID generation algorithm. See include/asm/mmu_context.h.
+ */
+
+ .llong 1 /* # ESIDs to be mapped by hypervisor */
+ .llong 1 /* # memory ranges to be mapped by hypervisor */
+ .llong 5 /* Page # of segment table within load area */
+ .llong 0 /* Reserved */
+ .llong 0 /* Reserved */
+ .llong 0 /* Reserved */
+ .llong 0 /* Reserved */
+ .llong 0 /* Reserved */
+ .llong 0x0c00000000 /* ESID to map (Kernel at EA = 0xC000000000000000) */
+ .llong 0x06a99b4b14 /* VSID to map (Kernel at VA = 0x6a99b4b140000000) */
+ .llong 8192 /* # pages to map (32 MB) */
+ .llong 0 /* Offset from start of loadarea to start of map */
+ .llong 0x0006a99b4b140000 /* VPN of first page to map */
+
+ . = 0x6100
+
+/*** ISeries-LPAR interrupt handlers ***/
+
+ STD_EXCEPTION_ISERIES( MachineCheck )
+ STD_EXCEPTION_ISERIES( DataAccess )
+ STD_EXCEPTION_ISERIES( DataAccessSLB )
+ STD_EXCEPTION_ISERIES( InstructionAccess )
+ STD_EXCEPTION_ISERIES( InstructionAccessSLB )
+ MASKABLE_EXCEPTION_ISERIES( HardwareInterrupt )
+ STD_EXCEPTION_ISERIES( Alignment )
+ STD_EXCEPTION_ISERIES( ProgramCheck )
+ STD_EXCEPTION_ISERIES( FPUnavailable )
+ MASKABLE_EXCEPTION_ISERIES( Decrementer )
+ STD_EXCEPTION_ISERIES( Trap_0a )
+ STD_EXCEPTION_ISERIES( Trap_0b )
+ STD_EXCEPTION_ISERIES( SystemCall )
+ STD_EXCEPTION_ISERIES( SingleStep )
+ STD_EXCEPTION_ISERIES( Trap_0e )
+ STD_EXCEPTION_ISERIES( PerformanceMonitor )
+
+ .globl SystemReset_Iseries
+SystemReset_Iseries:
+ 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(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 */
+ lis r3,0x8002
+ rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
+#else /* CONFIG_SMP */
+ /* Yield the processor. This is required for non-SMP kernels
+ which are running on multi-threaded machines. */
+ lis r3,0x8000
+ rldicr r3,r3,32,15 /* r3 = (r3 << 32) & 0xffff000000000000 */
+ 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 r25,SPRG3 /* Put r25 back ???? */
+ b 1b /* If SMP not configured, secondaries
+ * loop forever */
+
+ .globl HardwareInterrupt_Iseries_masked
+HardwareInterrupt_Iseries_masked:
+ b maskable_exception_exit
+
+ .globl Decrementer_Iseries_masked
+Decrementer_Iseries_masked:
+ li r22,1
+ stb r22,PACALPPACA+LPPACADECRINT(r20)
+ lwz r22,PACADEFAULTDECR(r20)
+ mtspr DEC,r22
+maskable_exception_exit:
+ mtcrf 0xff,r23 /* Restore regs and free exception frame */
+ ld r22,EX_SRR0(r21)
+ ld r23,EX_SRR1(r21)
+ mtspr SRR0,r22
+ mtspr SRR1,r23
+ ld r22,EX_R22(r21)
+ ld r23,EX_R23(r21)
+ mfspr r21,SPRG1
+ mfspr r20,SPRG2
+ rfid
+
+/*** Common interrupt handlers ***/
+
+ STD_EXCEPTION_COMMON( 0x100, SystemReset, .SystemResetException )
+ STD_EXCEPTION_COMMON( 0x200, MachineCheck, .MachineCheckException )
+ STD_EXCEPTION_COMMON( 0x900, Decrementer, .timer_interrupt )
+ STD_EXCEPTION_COMMON( 0xa00, Trap_0a, .UnknownException )
+ STD_EXCEPTION_COMMON( 0xb00, Trap_0b, .UnknownException )
+ STD_EXCEPTION_COMMON( 0xd00, SingleStep, .SingleStepException )
+ STD_EXCEPTION_COMMON( 0xe00, Trap_0e, .UnknownException )
+ STD_EXCEPTION_COMMON( 0xf00, PerformanceMonitor, .PerformanceMonitorException )
+ STD_EXCEPTION_COMMON(0x1300, InstructionBreakpoint, .InstructionBreakpointException )
+
+/*
+ * Return from an exception which is handled without calling
+ * save_remaining_regs. The caller is assumed to have done
+ * EXCEPTION_PROLOG_COMMON.
+ */
+fast_exception_return:
+ ld r3,_CCR(r1)
+ ld r4,_LINK(r1)
+ ld r5,_CTR(r1)
+ ld r6,_XER(r1)
+ mtcr r3
+ mtlr r4
+ mtctr r5
+ mtspr XER,r6
+ REST_GPR(0, r1)
+ REST_8GPRS(2, r1)
+ REST_4GPRS(10, r1)
+ mtspr SRR1,r23
+ mtspr SRR0,r22
+ REST_4GPRS(20, r1)
+ ld r1,GPR1(r1)
+ rfid
+
+
+/*
+ * Here r20 points to the PACA, r21 to the exception frame,
+ * r23 contains the saved CR.
+ * r20 - r23, SRR0 and SRR1 are saved in the exception frame.
+ */
+ .globl DataAccess_common
+DataAccess_common:
+ mfspr r22,DAR
+ srdi r22,r22,60
+ cmpi 0,r22,0xc
+
+ /* Segment fault on a bolted segment. Go off and map that segment. */
+ beq .do_stab_bolted
+stab_bolted_user_return:
+ EXCEPTION_PROLOG_COMMON
+ ld r3,_DSISR(r1)
+ andis. r0,r3,0xa450 /* weird error? */
+ bne 1f /* if not, try to put a PTE */
+ andis. r0,r3,0x0020 /* Is it a page table fault? */
+ rlwinm r4,r3,32-23,29,29 /* DSISR_STORE -> _PAGE_RW */
+ ld r3,_DAR(r1) /* into the hash table */
+
+ beq 2f /* If so handle it */
+ li r4,0x300 /* Trap number */
+ bl .do_stab_SI
+ b 1f
+
+2: bl .do_hash_page_DSI /* Try to handle as hpte fault */
+1:
+ ld r4,_DAR(r1)
+ ld r5,_DSISR(r1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+#ifdef DO_SOFT_DISABLE
+ ld r20,SOFTE(r1) /* Copy saved SOFTE bit */
+#else
+ rldicl r20,r23,49,63 /* copy EE bit from saved MSR */
+#endif
+ li r6,0x300
+ bl .save_remaining_regs
+ bl .do_page_fault
+ b .ret_from_except
+
+ .globl DataAccessSLB_common
+DataAccessSLB_common:
+ mfspr r22,DAR
+ srdi r22,r22,60
+ cmpi 0,r22,0xc
+
+ /* Segment fault on a bolted segment. Go off and map that segment. */
+ beq .do_slb_bolted
+
+ EXCEPTION_PROLOG_COMMON
+ ld r3,_DAR(r1)
+ li r4,0x380 /* Exception vector */
+ bl .ste_allocate
+ or. r3,r3,r3 /* Check return code */
+ beq fast_exception_return /* Return if we succeeded */
+ addi r3,r1,STACK_FRAME_OVERHEAD
+#ifdef DO_SOFT_DISABLE
+ ld r20,SOFTE(r1)
+#else
+ rldicl r20,r23,49,63 /* copy EE bit from saved MSR */
+#endif
+ li r6,0x380
+ bl .save_remaining_regs
+ bl .do_page_fault
+ b .ret_from_except
+
+ .globl InstructionAccess_common
+InstructionAccess_common:
+ EXCEPTION_PROLOG_COMMON
+
+ andis. r0,r23,0x0020 /* no ste found? */
+ beq 2f
+ mr r3,r22 /* SRR0 at interrupt */
+ li r4,0x400 /* Trap number */
+ bl .do_stab_SI
+ b 1f
+
+2: andis. r0,r23,0x4000 /* no pte found? */
+ beq 1f /* if so, try to put a PTE */
+ mr r3,r22 /* into the hash table */
+ bl .do_hash_page_ISI /* Try to handle as hpte fault */
+1:
+ mr r4,r22
+ mr r5,r23
+ addi r3,r1,STACK_FRAME_OVERHEAD
+#ifdef DO_SOFT_DISABLE
+ ld r20,SOFTE(r1)
+#else
+ rldicl r20,r23,49,63 /* copy EE bit from saved MSR */
+#endif
+ li r6,0x400
+ bl .save_remaining_regs
+ bl .do_page_fault
+ b .ret_from_except
+
+ .globl InstructionAccessSLB_common
+InstructionAccessSLB_common:
+ EXCEPTION_PROLOG_COMMON
+ mr r3,r22 /* SRR0 = NIA */
+ li r4,0x480 /* Exception vector */
+ bl .ste_allocate
+ or. r3,r3,r3 /* Check return code */
+ beq fast_exception_return /* Return if we succeeded */
+
+ addi r3,r1,STACK_FRAME_OVERHEAD
+#ifdef DO_SOFT_DISABLE
+ ld r20,SOFTE(r1)
+#else
+ rldicl r20,r23,49,63 /* copy EE bit from saved MSR */
+#endif
+ li r6,0x380
+ bl .save_remaining_regs
+ bl .do_page_fault
+ b .ret_from_except
+
+ .globl HardwareInterrupt_common
+HardwareInterrupt_common:
+ EXCEPTION_PROLOG_COMMON
+HardwareInterrupt_entry:
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,0
+ li r6,0x500
+ bl .save_remaining_regs
+ /* Determine if need to run do_irq on a hardware interrupt stack */
+ /* The first invocation of do_irq will occur on the kernel */
+ /* stack in the current stack */
+ /* All other invocations of do_irq will run on the hardware */
+ /* interrupt stack associated with the PACA of the current */
+ /* processor. */
+ /* */
+ /* The call to do_irq will preserve the value of r14 - r31 */
+ /* */
+ mfspr r20,SPRG3 /* get Paca */
+ lbz r21,PACAHRDWINTCOUNT(r20) /* get hardware interrupt cnt */
+ cmpi 0,r21,1 /* */
+ addi r21,r21,1 /* incr hardware interrupt cnt*/
+ stb r21,PACAHRDWINTCOUNT(r20) /* */
+ bne 2f /* */
+
+ mr r14,r1 /* preserve current r1 */
+ ld r1,PACAHRDWINTSTACK(r20) /* */
+ std r14,0(r1) /* set the back chain */
+ bl .do_IRQ
+ lbz r22,PACAHRDWINTCOUNT(r20) /* get hardware interrupt cnt */
+ cmp 0,r22,r21 /* debug test */
+ bne 3f
+ subi r21,r21,1
+ stb r21,PACAHRDWINTCOUNT(r20) /* */
+ mr r1,r14 /* */
+ b .ret_from_except
+
+2:
+ bl .do_IRQ
+
+ lbz r22,PACAHRDWINTCOUNT(r20) /* get hardware interrupt cnt */
+ cmp 0,r22,r21 /* debug test */
+ bne 3f /* */
+ subi r21,r21,1 /* decr hardware interrupt cnt*/
+ stb r21,PACAHRDWINTCOUNT(r20) /* */
+
+ b .ret_from_except
+
+3:
+ /* error - counts out of sync */
+#ifdef CONFIG_XMON
+ bl .xmon
+#endif
+4: b 4b
+
+
+ .globl Alignment_common
+Alignment_common:
+ EXCEPTION_PROLOG_COMMON
+ addi r3,r1,STACK_FRAME_OVERHEAD
+#ifdef DO_SOFT_DISABLE
+ ld r20,SOFTE(r1)
+#else
+ rldicl r20,r23,49,63 /* copy EE bit from saved MSR */
+#endif
+ li r6,0x600
+ bl .save_remaining_regs
+ bl .AlignmentException
+ b .ret_from_except
+
+ .globl ProgramCheck_common
+ProgramCheck_common:
+ EXCEPTION_PROLOG_COMMON
+ addi r3,r1,STACK_FRAME_OVERHEAD
+#ifdef DO_SOFT_DISABLE
+ ld r20,SOFTE(r1)
+#else
+ rldicl r20,r23,49,63 /* copy EE bit from saved MSR */
+#endif
+ li r6,0x700
+ bl .save_remaining_regs
+ bl .ProgramCheckException
+ b .ret_from_except
+
+ .globl FPUnavailable_common
+FPUnavailable_common:
+ EXCEPTION_PROLOG_COMMON
+ bne .load_up_fpu /* if from user, just load it up */
+ li r20,0
+ li r6,0x800
+ bl .save_remaining_regs /* if from kernel, take a trap */
+ bl .KernelFP
+ b .ret_from_except
+
+ .globl SystemCall_common
+SystemCall_common:
+ EXCEPTION_PROLOG_COMMON
+#ifdef CONFIG_PPC_ISERIES
+ 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:
+#endif
+ std r3,ORIG_GPR3(r1)
+#ifdef DO_SOFT_DISABLE
+ ld r20,SOFTE(r1)
+#else
+ rldicl r20,r23,49,63 /* copy EE bit from saved MSR */
+#endif
+ li r6,0xC00
+ bl .save_remaining_regs
+ bl .DoSyscall
+ b .ret_from_except
+
+_GLOBAL(do_hash_page_ISI)
+ li r4,0
+_GLOBAL(do_hash_page_DSI)
+ rlwimi r4,r23,32-13,30,30 /* Insert MSR_PR as _PAGE_USER */
+ ori r4,r4,1 /* add _PAGE_PRESENT */
+
+ mflr r21 /* Save LR in r21 */
+
+#ifdef DO_SOFT_DISABLE
+ /*
+ * We hard enable here (but first soft disable) so that the hash_page
+ * code can spin on the hash_table_lock with problem on a shared
+ * processor.
+ */
+ li r0,0
+ stb r0,PACAPROCENABLED(r20) /* Soft Disabled */
+
+ mfmsr r0
+ ori r0,r0,MSR_EE+MSR_RI
+ mtmsrd r0 /* Hard Enable, RI on */
+#endif
+
+ /*
+ * r3 contains the faulting address
+ * r4 contains the required access permissions
+ *
+ * at return r3 = 0 for success
+ */
+
+ bl .hash_page /* build HPTE if possible */
+
+#ifdef DO_SOFT_DISABLE
+ /*
+ * Now go back to hard disabled.
+ */
+ mfmsr r0
+ li r4,0
+ ori r4,r4,MSR_EE+MSR_RI
+ andc r0,r0,r4
+ mtmsrd r0 /* Hard Disable, RI off */
+
+ ld r0,SOFTE(r1)
+ cmpdi 0,r0,0 /* See if we will soft enable in */
+ /* save_remaining_regs */
+ beq 5f
+ CHECKANYINT(r4,r5)
+ bne- HardwareInterrupt_entry /* Convert this DSI into an External */
+ /* to process interrupts which occurred */
+ /* during hash_page */
+5:
+ stb r0,PACAPROCENABLED(r20) /* Restore soft enable/disable status */
+#endif
+ or. r3,r3,r3 /* Check return code */
+ beq fast_exception_return /* Return from exception on success */
+
+ mtlr r21 /* restore LR */
+ blr /* Return to DSI or ISI on failure */
+
+/*
+ * r20 points to the PACA, r21 to the exception frame,
+ * r23 contains the saved CR.
+ * r20 - r23, SRR0 and SRR1 are saved in the exception frame.
+ * We assume we aren't going to take any exceptions during this procedure.
+ */
+_GLOBAL(do_stab_bolted)
+ std r23,EX_DAR(r21) /* save CR in exc. frame */
+
+ mfspr r22,DSISR
+ andis. r22,r22,0x0020
+ bne+ 2f
+ ld r22,8(r21) /* get SRR1 */
+ andi. r22,r22,MSR_PR /* check if from user */
+ bne+ stab_bolted_user_return /* from user, send the error on up */
+ li r3,0
+#ifdef CONFIG_XMON
+ bl .xmon
+#endif
+1: b 1b
+2:
+ /* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */
+ mfspr r21,DAR
+ 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 */
+ sldi r21,r21,32
+ 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 r23,0(r21) /* Test valid bit of the current ste */
+ rldicl r23,r23,57,63
+ cmpwi r23,0
+ bne 2f
+ ld r23,8(r21) /* Get the current vsid part of the ste */
+ rldimi r23,r20,12,0 /* Insert the new vsid value */
+ std r23,8(r21) /* Put new entry back into the stab */
+ eieio /* Order vsid update */
+ ld r23,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 r23,r20,28,0 /* Insert the new esid value */
+ ori r23,r23,144 /* Turn on valid and kp */
+ std r23,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
+ or r21,r21,r22 /* r21 is the entry to invalidate */
+
+ isync /* mark the entry invalid */
+ ld r23,0(r21)
+ li r22,-129
+ and r23,r23,r22
+ std r23,0(r21)
+ sync
+
+ ld r23,8(r21)
+ rldimi r23,r20,12,0
+ std r23,8(r21)
+ eieio
+
+ ld r23,0(r21) /* Get the esid part of the ste */
+ mr r22,r23
+ mfspr r20,DAR /* Get the new esid */
+ rldicl r20,r20,36,28 /* Permits a full 32b of ESID */
+ rldimi r23,r20,28,0 /* Insert the new esid value */
+ ori r23,r23,144 /* Turn on valid and kp */
+ std r23,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 r21,PACAEXCSP(r20) /* Get the exception frame pointer */
+ addi r21,r21,EXC_FRAME_SIZE
+ ld r23,EX_DAR(r21) /* get saved CR */
+ /* note that this is almost identical to maskable_exception_exit */
+ mtcr r23 /* restore CR */
+ ld r22,EX_SRR0(r21) /* Get SRR0 from exc. frame */
+ ld r23,EX_SRR1(r21) /* Get SRR1 from exc. frame */
+ mtspr SRR0,r22
+ mtspr SRR1,r23
+ ld r22,EX_R22(r21) /* restore r22 and r23 */
+ ld r23,EX_R23(r21)
+ mfspr r20,SPRG2
+ mfspr r21,SPRG1
+ rfid
+_TRACEBACK(do_stab_bolted)
+
+/*
+ * r20 points to the PACA, r21 to the exception frame,
+ * r23 contains the saved CR.
+ * r20 - r23, SRR0 and SRR1 are saved in the exception frame.
+ * We assume we aren't going to take any exceptions during this procedure.
+ */
+_GLOBAL(do_slb_bolted)
+ std r23,48(r21) /* save CR in exc. frame */
+
+ /* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */
+ mfspr r21,DAR
+ 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 */
+ sldi r21,r21,32
+ oris r21,r21,58231
+ ori r21,r21,39831
+
+ mulld r20,r20,r21
+ clrldi r20,r20,28 /* r20 = vsid */
+
+ /* Search the SLB for a free entry */
+ li r22,1
+1:
+ slbmfee r23,r22
+ rldicl r23,r23,37,63
+ cmpwi r23,0
+ beq 3f /* Found an invalid entry */
+
+ addi r22,r22,1
+ cmpldi r22,64
+ blt 1b
+
+ /* No free entry - just take the next entry, round-robin */
+ /* XXX we should get the number of SLB entries from the naca */
+SLB_NUM_ENTRIES = 64
+ mfspr r21,SPRG3
+ ld r22,PACASTABRR(r21)
+ addi r23,r22,1
+ cmpdi r23,SLB_NUM_ENTRIES
+ blt 2f
+ li r23,1
+2: std r23,PACASTABRR(r21)
+
+ /* r20 = vsid, r22 = entry */
+3:
+ /* Put together the vsid portion of the entry. */
+ li r21,0
+ rldimi r21,r20,12,0
+ ori r20,r21,1024
+#ifndef CONFIG_PPC_ISERIES
+ ori r20,r20,256 /* map kernel region with large ptes */
+#endif
+
+ /* Put together the esid portion of the entry. */
+ mfspr r21,DAR /* Get the new esid */
+ rldicl r21,r21,36,28 /* Permits a full 36b of ESID */
+ li r23,0
+ rldimi r23,r21,28,0 /* Insert esid */
+ oris r21,r23,2048 /* valid bit */
+ rldimi r21,r22,0,52 /* Insert entry */
+
+ isync
+ slbmte r20,r21
+ isync
+
+ /* All done -- return from exception. */
+ mfsprg r20,3 /* Load the PACA pointer */
+ ld r21,PACAEXCSP(r20) /* Get the exception frame pointer */
+ addi r21,r21,EXC_FRAME_SIZE
+ ld r23,EX_DAR(r21) /* get saved CR */
+ /* note that this is almost identical to maskable_exception_exit */
+ mtcr r23 /* restore CR */
+ ld r22,EX_SRR0(r21) /* Get SRR0 from exc. frame */
+ ld r23,EX_SRR1(r21) /* Get SRR1 from exc. frame */
+ mtspr SRR0,r22
+ mtspr SRR1,r23
+ ld r22,EX_R22(r21) /* restore r22 and r23 */
+ ld r23,EX_R23(r21)
+ mfspr r20,SPRG2
+ mfspr r21,SPRG1
+ rfid
+_TRACEBACK(do_slb_bolted)
+
+_GLOBAL(do_stab_SI)
+ mflr r21 /* Save LR in r21 */
+
+ /*
+ * r3 contains the faulting address
+ * r4 contains the required access permissions
+ *
+ * at return r3 = 0 for success
+ */
+
+ bl .ste_allocate /* build STE if possible */
+ or. r3,r3,r3 /* Check return code */
+ beq fast_exception_return /* Return from exception on success */
+ mtlr r21 /* restore LR */
+ blr /* Return to DSI or ISI on failure */
+
+/*
+ * This code finishes saving the registers to the exception frame.
+ * Address translation is already on.
+ */
+_GLOBAL(save_remaining_regs)
+ /*
+ * Save the rest of the registers into the pt_regs structure
+ */
+ std r22,_NIP(r1)
+ std r23,_MSR(r1)
+ std r6,TRAP(r1)
+ ld r6,GPR6(r1)
+ SAVE_2GPRS(14, r1)
+ SAVE_4GPRS(16, r1)
+ SAVE_8GPRS(24, r1)
+
+ /*
+ * Clear the RESULT field
+ */
+ li r22,0
+ std r22,RESULT(r1)
+
+ /*
+ * Test if from user state; result will be tested later
+ */
+ 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
+ */
+ mfspr r23,SPRG3 /* Get PACA */
+ std r22,PACAKSAVE(r23) /* r1 is now kernel sp */
+ ld r2,PACATOC(r23) /* Get Kernel TOC pointer */
+
+ /*
+ * If from user state, update THREAD.regs
+ */
+ beq 2f /* Modify THREAD.regs if from user */
+ addi r24,r1,STACK_FRAME_OVERHEAD
+ std r24,THREAD+PT_REGS(r13)
+2:
+ SET_REG_TO_CONST(r22, MSR_KERNEL)
+
+#ifdef DO_SOFT_DISABLE
+ stb r20,PACAPROCENABLED(r23) /* possibly soft enable */
+ ori r22,r22,MSR_EE /* always hard enable */
+#else
+ rldimi r22,r20,15,48 /* Insert desired EE value */
+#endif
+
+ mtmsrd r22
+ blr
+
+
+do_profile:
+ ld r22,8(r21) /* Get SRR1 */
+ andi. r22,r22,MSR_PR /* Test if in kernel */
+ bnelr /* return if not in kernel */
+ ld r22,0(r21) /* Get SRR0 */
+ ld r25,PACAPROFSTEXT(r20) /* _stext */
+ subf r22,r25,r22 /* offset into kernel */
+ lwz r25,PACAPROFSHIFT(r20)
+ srd r22,r22,r25
+ lwz r25,PACAPROFLEN(r20) /* length of profile table (-1) */
+ cmp 0,r22,r25 /* off end? */
+ ble 1f
+ mr r22,r25 /* force into last entry */
+1: sldi r22,r22,2 /* convert to offset into buffer */
+ ld r25,PACAPROFBUFFER(r20) /* profile buffer */
+ add r25,r25,r22
+2: lwarx r22,0,r25 /* atomically increment */
+ addi r22,r22,1
+ stwcx. r22,0,r25
+ bne- 2b
+ blr
+
+
+/*
+ * On pSeries, secondary processors spin in the following code.
+ * 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. */
+
+ mtspr SPRG3,r25 /* Save vaddr of Paca in SPRG3 */
+ mr r24,r3 /* __secondary_start needs cpu# */
+
+1:
+ HMT_LOW
+ lbz r23,PACAPROCSTART(r25) /* Test if this processor should */
+ /* start. */
+ sync
+
+ /* Create a temp kernel stack for use before relocation is on. */
+ mr r1,r25
+ addi r1,r1,PACAGUARD
+ addi r1,r1,0x1000
+ subi r1,r1,STACK_FRAME_OVERHEAD
+
+ cmpi 0,r23,0
+#ifdef CONFIG_SMP
+#ifdef SECONDARY_PROCESSORS
+ bne .__secondary_start
+#endif
+#endif
+ b 1b /* Loop until told to go */
+
+_GLOBAL(__start_initialization_iSeries)
+
+ LOADADDR(r1,init_task_union)
+ addi r1,r1,TASK_UNION_SIZE
+ li r0,0
+ stdu r0,-STACK_FRAME_OVERHEAD(r1)
+
+ LOADADDR(r2,__toc_start)
+ addi r2,r2,0x4000
+ addi r2,r2,0x4000
+
+ LOADADDR(r9,naca)
+ SET_REG_TO_CONST(r4, KERNELBASE)
+ addi r4,r4,0x4000
+ std r4,0(r9) /* set the naca pointer */
+
+ /* Get the pointer to the segment table */
+ ld r6,PACA(r4) /* Get the base Paca pointer */
+ ld r4,PACASTABVIRT(r6)
+
+ bl .iSeries_fixup_klimit
+
+ b .start_here_common
+
+_GLOBAL(__start_initialization_pSeries)
+ mr r31,r3 /* save parameters */
+ mr r30,r4
+ mr r29,r5
+ mr r28,r6
+ mr r27,r7
+ mr r26,r8 /* YABOOT: debug_print() routine */
+ mr r25,r9 /* YABOOT: debug_delay() routine */
+ mr r24,r10 /* YABOOT: debug_prom() routine */
+
+ bl .enable_64b_mode
+
+ /* put a relocation offset into r3 */
+ bl .reloc_offset
+
+ LOADADDR(r2,__toc_start)
+ addi r2,r2,0x4000
+ addi r2,r2,0x4000
+
+ /* Relocate the TOC from a virt addr to a real addr */
+ sub r2,r2,r3
+
+ /* setup the naca pointer which is needed by prom_init */
+ LOADADDR(r9,naca)
+ sub r9,r9,r3 /* addr of the variable naca */
+
+ SET_REG_TO_CONST(r4, KERNELBASE)
+ sub r4,r4,r3
+ addi r4,r4,0x4000
+ std r4,0(r9) /* set the value of naca */
+
+ /* DRENG / PPPBBB Fix the following comment!!! -Peter */
+ /* The following copies the first 0x100 bytes of code from the */
+ /* load addr to physical addr 0x0. This code causes secondary */
+ /* processors to spin until a flag in the PACA is set. This */
+ /* is done at this time rather than with the entire kernel */
+ /* relocation which is done below because we need to cause the */
+ /* processors to spin on code that is not going to move while OF */
+ /* is still alive. Although the spin code is not actually run on */
+ /* a uniprocessor, we always do this copy. */
+ SET_REG_TO_CONST(r4, KERNELBASE)/* Src addr */
+ sub r4,r4,r3 /* current address of __start */
+ /* the source addr */
+ li r3,0 /* Dest addr */
+ li r5,0x100 /* # bytes of memory to copy */
+ li r6,0 /* Destination offset */
+ bl .copy_and_flush /* copy the first 0x100 bytes */
+
+ mr r3,r31
+ mr r4,r30
+ mr r5,r29
+ mr r6,r28
+ mr r7,r27
+ mr r8,r26
+ mr r9,r25
+ mr r10,r24
+
+ bl .prom_init
+
+ li r24,0 /* cpu # */
+
+/*
+ * At this point, r3 contains the physical address we are running at,
+ * returned by prom_init()
+ */
+_STATIC(__after_prom_start)
+
+/*
+ * We need to run with __start at physical address 0.
+ * This will leave some code in the first 256B of
+ * real memory, which are reserved for software use.
+ * The remainder of the first page is loaded with the fixed
+ * interrupt vectors. The next two pages are filled with
+ * unknown exception placeholders.
+ *
+ * Note: This process overwrites the OF exception vectors.
+ * r26 == relocation offset
+ * r27 == KERNELBASE
+ */
+ bl .reloc_offset
+ mr r26,r3
+ SET_REG_TO_CONST(r27,KERNELBASE)
+
+ li r3,0 /* target addr */
+
+ sub r4,r27,r26 /* source addr */
+ /* current address of _start */
+ /* i.e. where we are running */
+ /* the source addr */
+
+ LOADADDR(r5,copy_to_here) /* # bytes of memory to copy */
+ sub r5,r5,r27
+
+ li r6,0x100 /* Start offset, the first 0x100 */
+ /* bytes were copied earlier. */
+
+ bl .copy_and_flush /* copy the first n bytes */
+ /* this includes the code being */
+ /* executed here. */
+
+ li r0,4f@l /* Jump to the copy of this code */
+ mtctr r0 /* that we just made */
+ bctr
+
+4: LOADADDR(r9,rtas)
+ sub r9,r9,r26
+ ld r5,RTASBASE(r9) /* get the value of rtas->base */
+ ld r9,RTASSIZE(r9) /* get the value of rtas->size */
+ bl .copy_and_flush /* copy upto rtas->base */
+ add r6,r6,r9 /* then skip over rtas->size bytes */
+
+ LOADADDR(r5,klimit)
+ sub r5,r5,r26
+ ld r5,0(r5) /* get the value of klimit */
+ sub r5,r5,r27
+ bl .copy_and_flush /* copy the rest */
+ b .start_here_pSeries
+
+/*
+ * Copy routine used to copy the kernel to start at physical address 0
+ * and flush and invalidate the caches as needed.
+ * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset
+ * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5.
+ *
+ * Note: this routine *only* clobbers r0, r6 and lr
+ */
+_STATIC(copy_and_flush)
+ addi r5,r5,-8
+ addi r6,r6,-8
+4: li r0,16 /* Use the least common */
+ /* denominator cache line */
+ /* size. This results in */
+ /* extra cache line flushes */
+ /* but operation is correct. */
+ /* Can't get cache line size */
+ /* from NACA as it is being */
+ /* moved too. */
+
+ mtctr r0 /* put # words/line in ctr */
+3: addi r6,r6,8 /* copy a cache line */
+ ldx r0,r6,r4
+ stdx r0,r6,r3
+ bdnz 3b
+ dcbst r6,r3 /* write it to memory */
+ sync
+ icbi r6,r3 /* flush the icache line */
+ cmpld 0,r6,r5
+ blt 4b
+ sync
+ addi r5,r5,8
+ addi r6,r6,8
+ blr
+
+.align 8
+copy_to_here:
+
+/*
+ * Disable FP for the task which had the FPU previously,
+ * and save its floating-point registers in its thread_struct.
+ * Enables the FPU for use in the kernel on return.
+ * On SMP we know the fpu is free, since we give it up every
+ * switch. -- Cort
+ */
+_STATIC(load_up_fpu)
+ mfmsr r5 /* grab the current MSR */
+ ori r5,r5,MSR_FP
+ mtmsrd r5 /* enable use of fpu now */
+ isync
+/*
+ * For SMP, we don't do lazy FPU switching because it just gets too
+ * horrendously complex, especially when a task switches from one CPU
+ * to another. Instead we call giveup_fpu in switch_to.
+ *
+ */
+#ifndef CONFIG_SMP
+ LOADBASE(r3,last_task_used_math)
+ ld r4,last_task_used_math@l(r3)
+ cmpi 0,r4,0
+ beq 1f
+ addi r4,r4,THREAD /* want THREAD of last_task_used_math */
+ SAVE_32FPRS(0, r4)
+ mffs fr0
+ stfd fr0,THREAD_FPSCR-4(r4)
+ ld r5,PT_REGS(r4)
+ ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ li r20,MSR_FP|MSR_FE0|MSR_FE1
+ andc r4,r4,r20 /* disable FP for previous task */
+ std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#endif /* CONFIG_SMP */
+ /* enable use of FP after return */
+ ori r23,r23,MSR_FP|MSR_FE0|MSR_FE1
+ addi r5,r13,THREAD /* Get THREAD */
+ lfd fr0,THREAD_FPSCR-4(r5)
+ mtfsf 0xff,fr0
+ REST_32FPRS(0, r5)
+#ifndef CONFIG_SMP
+ subi r4,r5,THREAD /* Back to 'current' */
+ std r4,last_task_used_math@l(r3)
+#endif /* CONFIG_SMP */
+ /* restore registers and return */
+ b fast_exception_return
+
+/*
+ * FP unavailable trap from kernel - print a message, but let
+ * the task use FP in the kernel until it returns to user mode.
+ */
+_GLOBAL(KernelFP)
+ ld r3,_MSR(r1)
+ ori r3,r3,MSR_FP
+ std r3,_MSR(r1) /* enable use of FP after return */
+ LOADADDR(r3,86f)
+ mfspr r4,SPRG3 /* Get PACA */
+ ld r4,PACACURRENT(r4) /* current */
+ ld r5,_NIP(r1)
+ b .ret_from_except
+86: .string "floating point used in kernel (task=%p, pc=%x)\n"
+ .align 4
+
+/*
+ * giveup_fpu(tsk)
+ * Disable FP for the task given as the argument,
+ * and save the floating-point registers in its thread_struct.
+ * Enables the FPU for use in the kernel on return.
+ */
+_GLOBAL(giveup_fpu)
+ mfmsr r5
+ ori r5,r5,MSR_FP
+ mtmsrd r5 /* enable use of fpu now */
+ isync
+ cmpi 0,r3,0
+ beqlr- /* if no previous owner, done */
+ addi r3,r3,THREAD /* want THREAD of task */
+ ld r5,PT_REGS(r3)
+ cmpi 0,r5,0
+ SAVE_32FPRS(0, r3)
+ mffs fr0
+ stfd fr0,THREAD_FPSCR-4(r3)
+ beq 1f
+ ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ li r3,MSR_FP|MSR_FE0|MSR_FE1
+ andc r4,r4,r3 /* disable FP for previous task */
+ std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#ifndef CONFIG_SMP
+ li r5,0
+ LOADBASE(r4,last_task_used_math)
+ std r5,last_task_used_math@l(r4)
+#endif /* CONFIG_SMP */
+ blr
+
+
+
+#ifdef CONFIG_SMP
+/*
+ * This function is called after the master CPU has released the
+ * secondary processors. The execution environment is relocation off.
+ * The Paca for this processor has the following fields initialized at
+ * this point:
+ * 1. Processor number
+ * 2. Segment table pointer (virtual address)
+ * On entry the following are set:
+ * r1 = stack pointer. vaddr for iSeries, raddr (temp stack) for pSeries
+ * r24 = cpu# (in Linux terms)
+ * r25 = Paca virtual address
+ * SPRG3 = Paca virtual address
+ */
+_GLOBAL(__secondary_start)
+
+ HMT_MEDIUM /* Set thread priority to MEDIUM */
+
+ /* set up the TOC (virtual address) */
+ LOADADDR(r2,__toc_start)
+ addi r2,r2,0x4000
+ addi r2,r2,0x4000
+
+ std r2,PACATOC(r25)
+ li r6,0
+ std r6,PACAKSAVE(r25)
+ stb r6,PACAPROCENABLED(r25)
+
+#ifndef CONFIG_PPC_ISERIES
+ /* Initialize the page table pointer register. */
+ LOADADDR(r6,_SDR1)
+ ld r6,0(r6) /* get the value of _SDR1 */
+ mtspr SDR1,r6 /* set the htab location */
+#endif
+ /* Initialize the first segment table (or SLB) entry */
+ ld r3,PACASTABVIRT(r25) /* get addr of segment table */
+ bl .stab_initialize
+
+ /* Initialize the kernel stack. Just a repeat for iSeries. */
+ LOADADDR(r3,current_set)
+ sldi r28,r24,4 /* get current_set[cpu#] */
+ ldx r13,r3,r28
+ std r13,PACACURRENT(r25)
+ addi r1,r13,TASK_UNION_SIZE
+ subi r1,r1,STACK_FRAME_OVERHEAD
+
+ 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
+ li r7,0
+ mtlr r7
+
+ /* enable MMU and jump to start_secondary */
+ LOADADDR(r3,.start_secondary_prolog)
+ SET_REG_TO_CONST(r4, MSR_KERNEL)
+#ifdef DO_SOFT_DISABLE
+ ori r4,r4,MSR_EE
+#endif
+ mtspr SRR0,r3
+ mtspr SRR1,r4
+ rfid
+#endif /* CONFIG_SMP */
+
+/*
+ * Running with relocation on at this point. All we want to do is
+ * zero the stack back-chain pointer before going into C code.
+ */
+_GLOBAL(start_secondary_prolog)
+ li r3,0
+ std r3,0(r1) /* Zero the stack frame pointer */
+ bl .start_secondary
+
+/*
+ * This subroutine clobbers r11, r12 and the LR
+ */
+_GLOBAL(enable_64b_mode)
+ mfmsr r11 /* grab the current MSR */
+ li r12,1
+ rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
+ or r11,r11,r12
+ li r12,1
+ rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
+ or r11,r11,r12
+ mtmsrd r11
+ isync
+ blr
+
+/*
+ * This subroutine clobbers r11, r12 and the LR
+ */
+_GLOBAL(enable_32b_mode)
+ mfmsr r11 /* grab the current MSR */
+ li r12,1
+ rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
+ andc r11,r11,r12
+ li r12,1
+ rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
+ andc r11,r11,r12
+ mtmsrd r11
+ isync
+ blr
+
+
+/*
+ * This is where the main kernel code starts.
+ */
+_STATIC(start_here_pSeries)
+ /* get a new offset, now that the kernel has moved. */
+ bl .reloc_offset
+ mr r26,r3
+
+ /* setup the naca pointer which is needed by *tab_initialize */
+ LOADADDR(r6,naca)
+ sub r6,r6,r26 /* addr of the variable naca */
+ li r27,0x4000
+ std r27,0(r6) /* set the value of naca */
+
+#ifdef CONFIG_HMT
+ /* Start up the second thread on cpu 0 */
+ mfspr r3,PVR
+ srwi r3,r3,16
+ cmpwi r3,0x34 /* Pulsar */
+ beq 90f
+ cmpwi r3,0x36 /* Icestar */
+ beq 90f
+ cmpwi r3,0x37 /* SStar */
+ beq 90f
+ b 91f /* HMT not supported */
+90: li r3,0
+ bl .hmt_start_secondary
+91:
+#endif
+
+#ifdef CONFIG_SMP
+ /* All secondary cpus are now spinning on a common
+ * spinloop, release them all now so they can start
+ * to spin on their individual Paca spinloops.
+ * For non SMP kernels, the secondary cpus never
+ * get out of the common spinloop.
+ */
+ li r3,1
+ LOADADDR(r5,__secondary_hold_spinloop)
+ tophys(r4,r5)
+ std r3,0(r4)
+#endif
+
+ /* The following gets the stack and TOC set up with the regs */
+ /* pointing to the real addr of the kernel stack. This is */
+ /* all done to support the C function call below which sets */
+ /* up the htab. This is done because we have relocated the */
+ /* kernel but are still running in real mode. */
+
+ /* real ptr to current */
+ LOADADDR(r3,init_task_union)
+ sub r3,r3,r26
+
+ /* set up a stack pointer (physical address) */
+ addi r1,r3,TASK_UNION_SIZE
+ li r0,0
+ stdu r0,-STACK_FRAME_OVERHEAD(r1)
+
+ /* set up the TOC (physical address) */
+ LOADADDR(r2,__toc_start)
+ addi r2,r2,0x4000
+ addi r2,r2,0x4000
+ sub r2,r2,r26
+
+ /* Init naca->debug_switch so it can be used in stab & htab init. */
+ bl .ppcdbg_initialize
+
+ /* Get the pointer to the segment table which is used by */
+ /* stab_initialize */
+ li r27,0x4000
+ ld r6,PACA(r27) /* Get the base Paca pointer */
+ sub r6,r6,r26 /* convert to physical addr */
+ mtspr SPRG3,r6 /* PPPBBB: Temp... -Peter */
+ ld r3,PACASTABREAL(r6)
+ ori r4,r3,1 /* turn on valid bit */
+ mtasr r4 /* set the stab location */
+
+ /* Initialize an initial memory mapping and turn on relocation. */
+ bl .stab_initialize
+ bl .htab_initialize
+
+ LOADADDR(r6,_SDR1)
+ sub r6,r6,r26
+ ld r6,0(r6) /* get the value of _SDR1 */
+ mtspr SDR1,r6 /* set the htab location */
+
+ LOADADDR(r3,.start_here_common)
+ SET_REG_TO_CONST(r4, MSR_KERNEL)
+ mtspr SRR0,r3
+ mtspr SRR1,r4
+ rfid
+
+ /* This is where all platforms converge execution */
+_STATIC(start_here_common)
+ /* relocation is on at this point */
+
+ /* Clear out the BSS */
+ LOADADDR(r11,_end)
+
+ LOADADDR(r8,__bss_start)
+
+ sub r11,r11,r8 /* bss size */
+ addi r11,r11,7 /* round up to an even double word */
+ rldicl. r11,r11,61,3 /* shift right by 3 */
+ beq 4f
+ addi r8,r8,-8
+ li r0,0
+ mtctr r11 /* zero this many doublewords */
+3: stdu r0,8(r8)
+ bdnz 3b
+4:
+
+ /* The following code sets up the SP and TOC now that we are */
+ /* running with translation enabled. */
+
+ /* ptr to current */
+ LOADADDR(r3,init_task_union)
+
+ /* set up the stack */
+ addi r1,r3,TASK_UNION_SIZE
+ li r0,0
+ stdu r0,-STACK_FRAME_OVERHEAD(r1)
+
+ /* set up the TOC */
+ LOADADDR(r2,__toc_start)
+ addi r2,r2,0x4000
+ addi r2,r2,0x4000
+
+ /* setup the naca pointer */
+ LOADADDR(r9,naca)
+
+ SET_REG_TO_CONST(r8, KERNELBASE)
+ addi r8,r8,0x4000
+ std r8,0(r9) /* set the value of the naca ptr */
+
+ LOADADDR(r4,naca) /* Get Naca ptr address */
+ ld r4,0(r4) /* Get the location of the naca */
+ ld r4,PACA(r4) /* Get the base Paca pointer */
+ mtspr SPRG3,r4
+
+ /* ptr to current */
+ LOADADDR(r13,init_task_union)
+ std r13,PACACURRENT(r4)
+
+ std r2,PACATOC(r4)
+ li r5,0
+ std r0,PACAKSAVE(r4)
+
+ /* ptr to hardware interrupt stack for processor 0 */
+ LOADADDR(r3, hardware_int_paca0)
+ li r5,0x1000
+ sldi r5,r5,3
+ subi r5,r5,STACK_FRAME_OVERHEAD
+
+ add r3,r3,r5
+ std r3,PACAHRDWINTSTACK(r4)
+
+ li r3,0
+ stb r3,PACAHRDWINTCOUNT(r4)
+
+
+ /*
+ * Restore the parms passed in from the bootloader.
+ */
+ mr r3,r31
+ mr r4,r30
+ mr r5,r29
+ mr r6,r28
+ mr r7,r27
+
+ bl .setup_system
+
+ /* Load up the kernel context */
+5:
+#ifdef DO_SOFT_DISABLE
+ mfspr r4,SPRG3
+ li r5,0
+ stb r5,PACAPROCENABLED(r4) /* Soft Disabled */
+ mfmsr r5
+ ori r5,r5,MSR_EE /* Hard Enabled */
+ mtmsrd r5
+#endif
+
+ bl .start_kernel
+
+_GLOBAL(hmt_init)
+#ifdef CONFIG_HMT
+ LOADADDR(r5, hmt_thread_data)
+ mfspr r7,PVR
+ srwi r7,r7,16
+ cmpwi r7,0x34 /* Pulsar */
+ beq 90f
+ cmpwi r7,0x36 /* Icestar */
+ beq 91f
+ cmpwi r7,0x37 /* SStar */
+ beq 91f
+ b 101f
+90: mfspr r6,PIR
+ andi. r6,r6,0x1f
+ b 92f
+91: mfspr r6,PIR
+ andi. r6,r6,0x3ff
+92: sldi r4,r24,3
+ stwx r6,r5,r4
+ bl .hmt_start_secondary
+ b 101f
+
+__hmt_secondary_hold:
+ LOADADDR(r5, hmt_thread_data)
+ clrldi r5,r5,4
+ li r7,0
+ mfspr r6,PIR
+ mfspr r8,PVR
+ srwi r8,r8,16
+ cmpwi r8,0x34
+ bne 93f
+ andi. r6,r6,0x1f
+ b 103f
+93: andi. r6,r6,0x3f
+
+103: lwzx r8,r5,r7
+ cmpw r8,r6
+ beq 104f
+ addi r7,r7,8
+ b 103b
+
+104: addi r7,r7,4
+ lwzx r9,r5,r7
+ mr r24,r9
+101:
+#endif
+ mr r3,r24
+ b .pseries_secondary_smp_init
+
+#ifdef CONFIG_HMT
+_GLOBAL(hmt_start_secondary)
+ LOADADDR(r4,__hmt_secondary_hold)
+ clrldi r4,r4,4
+ mtspr NIADORM, r4
+ mfspr r4, MSRDORM
+ li r5, -65
+ and r4, r4, r5
+ mtspr MSRDORM, r4
+ lis r4,0xffef
+ ori r4,r4,0x7403
+ mtspr TSC, r4
+ li r4,0x1f4
+ mtspr TST, r4
+ mfspr r4, HID0
+ ori r4, r4, 0x1
+ mtspr HID0, r4
+ mfspr r4, CTRLF
+ oris r4, r4, 0x40
+ mtspr CTRLT, r4
+ blr
+#endif
+
+/*
+ * We put a few things here that have to be page-aligned.
+ * This stuff goes at the beginning of the data segment,
+ * which is page-aligned.
+ */
+ .data
+ .align 12
+ .globl sdata
+sdata:
+ .globl empty_zero_page
+empty_zero_page:
+ .space 4096
+
+ .globl swapper_pg_dir
+swapper_pg_dir:
+ .space 4096
+
+ .globl ioremap_dir
+ioremap_dir:
+ .space 4096
+
+ .globl hardware_int_paca0
+hardware_int_paca0:
+ .space 8*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.
+ */
+ .globl cmd_line
+cmd_line:
+ .space 512
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/htab.c linuxppc64_2_4/arch/ppc64/kernel/htab.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/htab.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/htab.c Fri Feb 8 11:22:17 2002
@@ -0,0 +1,1230 @@
+/*
+ *
+ *
+ * PowerPC64 port by Mike Corrigan and Dave Engebretsen
+ * {mikejc|engebret}@us.ibm.com
+ *
+ * Copyright (c) 2000 Mike Corrigan
+ *
+ * Module name: htab.c
+ *
+ * Description:
+ * PowerPC Hashed Page Table functions
+ *
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#ifdef CONFIG_PPC_EEH
+#include
+#endif
+
+/* For iSeries */
+#include
+
+/* Note: pte --> Linux PTE
+ * HPTE --> PowerPC Hashed Page Table Entry
+ */
+
+HTAB htab_data = {NULL, 0, 0, 0, 0};
+
+int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp);
+
+void htab_initialize(void);
+void make_pte_LPAR(HPTE *htab,
+ unsigned long va, unsigned long pa, int mode,
+ unsigned long hash_mask, int large);
+
+extern unsigned long reloc_offset(void);
+extern unsigned long get_kernel_vsid( unsigned long ea );
+extern void cacheable_memzero( void *, unsigned int );
+
+extern unsigned long _SDR1;
+extern unsigned long klimit;
+extern struct Naca *naca;
+
+extern unsigned long _ASR;
+extern inline void make_ste(unsigned long stab,
+ unsigned long esid, unsigned long vsid);
+
+extern char _stext[], _etext[], __start_naca[], __end_stab[];
+
+static spinlock_t hash_table_lock ____cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+
+#define PTRRELOC(x) ((typeof(x))((unsigned long)(x) - offset))
+#define PTRUNRELOC(x) ((typeof(x))((unsigned long)(x) + offset))
+#define RELOC(x) (*PTRRELOC(&(x)))
+
+extern unsigned long htab_size( unsigned long );
+unsigned long hpte_getword0_iSeries( unsigned long slot );
+
+#define KB (1024)
+#define MB (1024*KB)
+static inline void
+create_pte_mapping(unsigned long start, unsigned long end,
+ unsigned long mode, unsigned long mask, int large)
+{
+ unsigned long addr, offset = reloc_offset();
+ HTAB *_htab_data = PTRRELOC(&htab_data);
+ HPTE *htab = (HPTE *)__v2a(_htab_data->htab);
+ unsigned int step;
+
+ if (large)
+ step = 16*MB;
+ else
+ step = 4*KB;
+
+ for (addr = start; addr < end; addr += step) {
+ unsigned long vsid = get_kernel_vsid(addr);
+ unsigned long va = (vsid << 28) | (addr & 0xfffffff);
+ make_pte(htab, va, (unsigned long)__v2a(addr), mode, mask,
+ large);
+ }
+}
+
+void
+htab_initialize(void)
+{
+ unsigned long table, htab_size_bytes;
+ unsigned long pteg_count;
+ unsigned long mode_ro, mode_rw, mask;
+ unsigned long offset = reloc_offset();
+ struct Naca *_naca = RELOC(naca);
+ HTAB *_htab_data = PTRRELOC(&htab_data);
+
+ /*
+ * Calculate the required size of the htab. We want the number of
+ * PTEGs to equal one half the number of real pages.
+ */
+ htab_size_bytes = 1UL << _naca->pftSize;
+ pteg_count = htab_size_bytes >> 7;
+
+ /* For debug, make the HTAB 1/8 as big as it normally would be. */
+ ifppcdebug(PPCDBG_HTABSIZE) {
+ pteg_count >>= 3;
+ htab_size_bytes = pteg_count << 7;
+ }
+
+ _htab_data->htab_num_ptegs = pteg_count;
+ _htab_data->htab_hash_mask = pteg_count - 1;
+
+ if(_machine == _MACH_pSeries) {
+ /* Find storage for the HPT. Must be contiguous in
+ * the absolute address space.
+ */
+ table = lmb_alloc(htab_size_bytes, htab_size_bytes);
+ if ( !table )
+ panic("ERROR, cannot find space for HPTE\n");
+ _htab_data->htab = (HPTE *)__a2v(table);
+
+ /* htab absolute addr + encoded htabsize */
+ RELOC(_SDR1) = table + __ilog2(pteg_count) - 11;
+
+ /* Initialize the HPT with no entries */
+ cacheable_memzero((void *)table, htab_size_bytes);
+ } else {
+ _htab_data->htab = NULL;
+ RELOC(_SDR1) = 0;
+ }
+
+ mode_ro = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RXRX;
+ mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
+ mask = pteg_count-1;
+
+ /* Create PTE's for the kernel text and data sections plus
+ * the HPT and HPTX arrays. Make the assumption that
+ * (addr & KERNELBASE) == 0 (ie they are disjoint).
+ * We also assume that the va is <= 64 bits.
+ */
+#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
+#ifndef CONFIG_PPC_ISERIES
+ if (__is_processor(PV_POWER4) && _naca->physicalMemorySize > 256*MB) {
+ create_pte_mapping((unsigned long)KERNELBASE,
+ KERNELBASE + 256*MB, mode_rw, mask, 0);
+ create_pte_mapping((unsigned long)KERNELBASE + 256*MB,
+ KERNELBASE + (_naca->physicalMemorySize),
+ mode_rw, mask, 1);
+ return;
+ }
+#endif
+ create_pte_mapping((unsigned long)KERNELBASE,
+ KERNELBASE+(_naca->physicalMemorySize),
+ mode_rw, mask, 0);
+#endif
+}
+#undef KB
+#undef MB
+
+/*
+ * Create a pte. Used during initialization only.
+ * We assume the PTE will fit in the primary PTEG.
+ */
+void make_pte(HPTE *htab,
+ unsigned long va, unsigned long pa, int mode,
+ unsigned long hash_mask, int large)
+{
+ HPTE *hptep;
+ unsigned long hash, i;
+ volatile unsigned long x = 1;
+ unsigned long vpn;
+
+#ifdef CONFIG_PPC_PSERIES
+ if(_machine == _MACH_pSeriesLP) {
+ make_pte_LPAR(htab, va, pa, mode, hash_mask, large);
+ return;
+ }
+#endif
+
+ if (large)
+ vpn = va >> 24;
+ else
+ vpn = va >> 12;
+
+ hash = hpt_hash(vpn, large);
+
+ hptep = htab + ((hash & hash_mask)*HPTES_PER_GROUP);
+
+ for (i = 0; i < 8; ++i, ++hptep) {
+ if ( hptep->dw0.dw0.v == 0 ) { /* !valid */
+ hptep->dw1.dword1 = pa | mode;
+ hptep->dw0.dword0 = 0;
+ hptep->dw0.dw0.avpn = va >> 23;
+ hptep->dw0.dw0.bolted = 1; /* bolted */
+ hptep->dw0.dw0.v = 1; /* make valid */
+ return;
+ }
+ }
+
+ /* We should _never_ get here and too early to call xmon. */
+ for(;x;x|=1);
+}
+
+/* Functions to invalidate a HPTE */
+static void hpte_invalidate_iSeries( unsigned long slot )
+{
+ HvCallHpt_invalidateSetSwBitsGet( slot, 0, 0 );
+}
+
+static void hpte_invalidate_pSeries( unsigned long slot )
+{
+ /* Local copy of the first doubleword of the HPTE */
+ union {
+ unsigned long d;
+ Hpte_dword0 h;
+ } hpte_dw0;
+
+ /* Locate the HPTE */
+ HPTE * hptep = htab_data.htab + slot;
+
+ /* Get the first doubleword of the HPTE */
+ hpte_dw0.d = hptep->dw0.dword0;
+
+ /* Invalidate the hpte */
+ hptep->dw0.dword0 = 0;
+
+ /* Invalidate the tlb */
+ {
+ unsigned long vsid, group, pi, pi_high;
+
+ vsid = hpte_dw0.h.avpn >> 5;
+ group = slot >> 3;
+ if(hpte_dw0.h.h) {
+ group = ~group;
+ }
+ pi = (vsid ^ group) & 0x7ff;
+ pi_high = (hpte_dw0.h.avpn & 0x1f) << 11;
+ pi |= pi_high;
+ _tlbie(pi << 12);
+ }
+}
+
+
+/* Select an available HPT slot for a new HPTE
+ * return slot index (if in primary group)
+ * return -slot index (if in secondary group)
+ */
+static long hpte_selectslot_iSeries( unsigned long vpn )
+{
+ HPTE hpte;
+ long ret_slot, orig_slot;
+ unsigned long primary_hash;
+ unsigned long hpteg_slot;
+ unsigned long slot;
+ unsigned i, k;
+ union {
+ unsigned long d;
+ Hpte_dword0 h;
+ } hpte_dw0;
+
+ ret_slot = orig_slot = HvCallHpt_findValid( &hpte, vpn );
+ if ( hpte.dw0.dw0.v ) { /* If valid ...what do we do now? */
+ udbg_printf( "hpte_selectslot_iSeries: vpn 0x%016lx already valid at slot 0x%016lx\n", vpn, ret_slot );
+ udbg_printf( "hpte_selectslot_iSeries: returned hpte 0x%016lx 0x%016lx\n", hpte.dw0.dword0, hpte.dw1.dword1 );
+
+ return (0x8000000000000000);
+ /* panic("select_hpte_slot found entry already valid\n"); */
+ }
+ if ( ret_slot == -1 ) { /* -1 indicates no available slots */
+
+ /* No available entry found in secondary group */
+
+ PMC_SW_SYSTEM(htab_capacity_castouts);
+
+ primary_hash = hpt_hash(vpn, 0);
+ hpteg_slot = ( primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP;
+ k = htab_data.next_round_robin++ & 0x7;
+
+ for ( i=0; idw0.dw0.v == 0 ) {
+ /* If an available slot found, return it */
+ return hpteg_slot + i;
+ }
+ hptep++;
+ }
+
+ /* No available entry found in primary group */
+
+ PMC_SW_SYSTEM(htab_primary_overflows);
+
+ /* Search the secondary group */
+
+ hpteg_slot = ( ~primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP;
+ hptep = htab_data.htab + hpteg_slot;
+
+ for (i=0; idw0.dw0.v == 0 ) {
+ /* If an available slot found, return it */
+ return -(hpteg_slot + i);
+ }
+ hptep++;
+ }
+
+ /* No available entry found in secondary group */
+
+ PMC_SW_SYSTEM(htab_capacity_castouts);
+
+ /* Select an entry in the primary group to replace */
+
+ hpteg_slot = ( primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP;
+ hptep = htab_data.htab + hpteg_slot;
+ k = htab_data.next_round_robin++ & 0x7;
+
+ for (i=0; idw0.dword0;
+ return dword0;
+}
+
+static long hpte_find_iSeries(unsigned long vpn)
+{
+ HPTE hpte;
+ long slot;
+
+ slot = HvCallHpt_findValid( &hpte, vpn );
+ if ( hpte.dw0.dw0.v ) {
+ if ( slot < 0 ) {
+ slot &= 0x7fffffffffffffff;
+ slot = -slot;
+ }
+ } else
+ slot = -1;
+ return slot;
+}
+
+static long hpte_find_pSeries(unsigned long vpn)
+{
+ union {
+ unsigned long d;
+ Hpte_dword0 h;
+ } hpte_dw0;
+ long slot;
+ unsigned long hash;
+ unsigned long i,j;
+
+ hash = hpt_hash(vpn, 0);
+ 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;
+ }
+ return -1;
+}
+
+/* This function is called by iSeries setup when initializing the hpt */
+void build_valid_hpte( unsigned long vsid, unsigned long ea, unsigned long pa,
+ pte_t * ptep, unsigned hpteflags, unsigned bolted )
+{
+ unsigned long vpn, flags;
+ long hpte_slot;
+ unsigned hash;
+ pte_t pte;
+
+ vpn = ((vsid << 28) | ( ea & 0xffff000 )) >> 12;
+
+ spin_lock_irqsave( &hash_table_lock, flags );
+
+ hpte_slot = ppc_md.hpte_selectslot( vpn );
+ hash = 0;
+ if ( hpte_slot < 0 ) {
+ if ( hpte_slot == 0x8000000000000000 ) {
+ udbg_printf("hash_page: ptep = 0x%016lx\n",
+ (unsigned long)ptep );
+ udbg_printf("hash_page: ea = 0x%016lx\n", ea );
+ udbg_printf("hash_page: vpn = 0x%016lx\n", vpn );
+
+ panic("hash_page: hpte already exists\n");
+ }
+ hash = 1;
+ hpte_slot = -hpte_slot;
+ }
+ ppc_md.hpte_create_valid( hpte_slot, vpn, pa >> 12, hash, ptep,
+ hpteflags, bolted );
+
+ if ( ptep ) {
+ /* Get existing pte flags */
+ pte = *ptep;
+ pte_val(pte) &= ~_PAGE_HPTEFLAGS;
+
+ /* Add in the has hpte flag */
+ pte_val(pte) |= _PAGE_HASHPTE;
+
+ /* Add in the _PAGE_SECONDARY flag */
+ pte_val(pte) |= hash << 15;
+
+ /* Add in the hpte slot */
+ pte_val(pte) |= (hpte_slot << 12) & _PAGE_GROUP_IX;
+
+ /* Save the new pte. */
+ *ptep = pte;
+
+ }
+ spin_unlock_irqrestore( &hash_table_lock, flags );
+}
+
+
+/* Create an HPTE and validate it
+ * It is assumed that the HPT slot currently is invalid.
+ * The HPTE is set with the vpn, rpn (converted to absolute)
+ * and flags
+ */
+static void hpte_create_valid_iSeries(unsigned long slot, unsigned long vpn,
+ unsigned long prpn, unsigned hash,
+ void * ptep, unsigned hpteflags,
+ unsigned bolted )
+{
+ /* Local copy of HPTE */
+ struct {
+ /* Local copy of first doubleword of HPTE */
+ union {
+ unsigned long d;
+ Hpte_dword0 h;
+ } dw0;
+ /* Local copy of second doubleword of HPTE */
+ union {
+ unsigned long d;
+ Hpte_dword1 h;
+ Hpte_dword1_flags f;
+ } dw1;
+ } lhpte;
+
+ unsigned long avpn = vpn >> 11;
+ unsigned long arpn = physRpn_to_absRpn( prpn );
+
+ /* Fill in the local HPTE with absolute rpn, avpn and flags */
+ lhpte.dw1.d = 0;
+ lhpte.dw1.h.rpn = arpn;
+ lhpte.dw1.f.flags = hpteflags;
+
+ lhpte.dw0.d = 0;
+ lhpte.dw0.h.avpn = avpn;
+ lhpte.dw0.h.h = hash;
+ lhpte.dw0.h.bolted = bolted;
+ lhpte.dw0.h.v = 1;
+
+ /* Now fill in the actual HPTE */
+ HvCallHpt_addValidate( slot, hash, (HPTE *)&lhpte );
+}
+
+static void hpte_create_valid_pSeries(unsigned long slot, unsigned long vpn,
+ unsigned long prpn, unsigned hash,
+ void * ptep, unsigned hpteflags,
+ unsigned bolted)
+{
+ /* Local copy of HPTE */
+ struct {
+ /* Local copy of first doubleword of HPTE */
+ union {
+ unsigned long d;
+ Hpte_dword0 h;
+ } dw0;
+ /* Local copy of second doubleword of HPTE */
+ union {
+ unsigned long d;
+ Hpte_dword1 h;
+ Hpte_dword1_flags f;
+ } dw1;
+ } lhpte;
+
+ unsigned long avpn = vpn >> 11;
+ unsigned long arpn = physRpn_to_absRpn( prpn );
+
+ HPTE *hptep;
+
+ /* Fill in the local HPTE with absolute rpn, avpn and flags */
+ lhpte.dw1.d = 0;
+ lhpte.dw1.h.rpn = arpn;
+ lhpte.dw1.f.flags = hpteflags;
+
+ lhpte.dw0.d = 0;
+ lhpte.dw0.h.avpn = avpn;
+ lhpte.dw0.h.h = hash;
+ lhpte.dw0.h.bolted = bolted;
+ lhpte.dw0.h.v = 1;
+
+ /* Now fill in the actual HPTE */
+ hptep = htab_data.htab + slot;
+
+ /* Set the second dword first so that the valid bit
+ * is the last thing set
+ */
+
+ hptep->dw1.dword1 = lhpte.dw1.d;
+
+ /* Guarantee the second dword is visible before
+ * the valid bit
+ */
+
+ __asm__ __volatile__ ("eieio" : : : "memory");
+
+ /* Now set the first dword including the valid bit */
+ hptep->dw0.dword0 = lhpte.dw0.d;
+
+ __asm__ __volatile__ ("ptesync" : : : "memory");
+}
+
+/* find_linux_pte returns the address of a linux pte for a given
+ * effective address and directory. If not found, it returns zero.
+ */
+
+pte_t * find_linux_pte( pgd_t * pgdir, unsigned long ea )
+{
+ pgd_t *pg;
+ pmd_t *pm;
+ pte_t *pt = NULL;
+ pte_t pte;
+ pg = pgdir + pgd_index( ea );
+ if ( ! pgd_none( *pg ) ) {
+
+ pm = pmd_offset( pg, ea );
+ if ( ! pmd_none( *pm ) ) {
+ pt = pte_offset( pm, ea );
+ pte = *pt;
+ if ( ! pte_present( pte ) )
+ pt = NULL;
+ }
+ }
+
+ return pt;
+
+}
+
+static inline unsigned long computeHptePP( unsigned long pte )
+{
+ return ( pte & _PAGE_USER ) |
+ ( ( ( pte & _PAGE_USER ) >> 1 ) &
+ ( ( ~( ( pte >> 2 ) & /* _PAGE_RW */
+ ( pte >> 7 ) ) ) & /* _PAGE_DIRTY */
+ 1 ) );
+}
+
+static void hpte_updatepp_iSeries(long slot, unsigned long newpp, unsigned long va)
+{
+ HvCallHpt_setPp( slot, newpp );
+}
+
+static void hpte_updatepp_pSeries(long slot, unsigned long newpp, unsigned long va)
+{
+ /* Local copy of first doubleword of HPTE */
+ union {
+ unsigned long d;
+ Hpte_dword0 h;
+ } hpte_dw0;
+
+ /* Local copy of second doubleword of HPTE */
+ union {
+ unsigned long d;
+ Hpte_dword1 h;
+ Hpte_dword1_flags f;
+ } hpte_dw1;
+
+ HPTE * hptep = htab_data.htab + slot;
+
+ /* Turn off valid bit in HPTE */
+ hpte_dw0.d = hptep->dw0.dword0;
+ hpte_dw0.h.v = 0;
+ hptep->dw0.dword0 = hpte_dw0.d;
+
+ /* Ensure it is out of the tlb too */
+ _tlbie( va );
+
+ /* Insert the new pp bits into the HPTE */
+ hpte_dw1.d = hptep->dw1.dword1;
+ hpte_dw1.h.pp = newpp;
+ hptep->dw1.dword1 = hpte_dw1.d;
+
+ /* Ensure it is visible before validating */
+ __asm__ __volatile__ ("eieio" : : : "memory");
+
+ /* Turn the valid bit back on in HPTE */
+ hpte_dw0.h.v = 1;
+ hptep->dw0.dword0 = hpte_dw0.d;
+
+ __asm__ __volatile__ ("ptesync" : : : "memory");
+}
+
+/*
+ * Update the page protection bits. Intended to be used to create
+ * guard pages for kernel data structures on pages which are bolted
+ * in the HPT. Assumes pages being operated on will not be stolen.
+ */
+void hpte_updateboltedpp_iSeries(unsigned long newpp, unsigned long ea )
+{
+ unsigned long vsid,va,vpn;
+ long slot;
+
+ vsid = get_kernel_vsid( ea );
+ va = ( vsid << 28 ) | ( ea & 0x0fffffff );
+ vpn = va >> PAGE_SHIFT;
+
+ slot = ppc_md.hpte_find( vpn );
+ HvCallHpt_setPp( slot, newpp );
+}
+
+
+static __inline__ void set_pp_bit(unsigned long pp, HPTE *addr)
+{
+ unsigned long old;
+ unsigned long *p = (unsigned long *)(&(addr->dw1));
+
+ __asm__ __volatile__(
+ "1: ldarx %0,0,%3\n\
+ rldimi %0,%2,0,62\n\
+ stdcx. %0,0,%3\n\
+ bne 1b"
+ : "=&r" (old), "=m" (*p)
+ : "r" (pp), "r" (p), "m" (*p)
+ : "cc");
+}
+
+/*
+ * Update the page protection bits. Intended to be used to create
+ * guard pages for kernel data structures on pages which are bolted
+ * in the HPT. Assumes pages being operated on will not be stolen.
+ */
+void hpte_updateboltedpp_pSeries(unsigned long newpp, unsigned long ea)
+{
+ unsigned long vsid,va,vpn,flags;
+ long slot;
+ HPTE *hptep;
+
+ vsid = get_kernel_vsid( ea );
+ va = ( vsid << 28 ) | ( ea & 0x0fffffff );
+ vpn = va >> PAGE_SHIFT;
+
+ slot = ppc_md.hpte_find( vpn );
+ hptep = htab_data.htab + slot;
+
+ set_pp_bit(newpp , hptep);
+
+ /* Ensure it is out of the tlb too */
+ spin_lock_irqsave( &hash_table_lock, flags );
+ _tlbie( va );
+ spin_unlock_irqrestore( &hash_table_lock, flags );
+}
+
+
+
+/* This is called very early. */
+void hpte_init_iSeries(void)
+{
+ ppc_md.hpte_invalidate = hpte_invalidate_iSeries;
+ ppc_md.hpte_updatepp = hpte_updatepp_iSeries;
+ ppc_md.hpte_updateboltedpp = hpte_updateboltedpp_iSeries;
+ ppc_md.hpte_getword0 = hpte_getword0_iSeries;
+ ppc_md.hpte_selectslot = hpte_selectslot_iSeries;
+ ppc_md.hpte_create_valid = hpte_create_valid_iSeries;
+ ppc_md.hpte_find = hpte_find_iSeries;
+}
+void hpte_init_pSeries(void)
+{
+ ppc_md.hpte_invalidate = hpte_invalidate_pSeries;
+ ppc_md.hpte_updatepp = hpte_updatepp_pSeries;
+ ppc_md.hpte_updateboltedpp = hpte_updateboltedpp_pSeries;
+ ppc_md.hpte_getword0 = hpte_getword0_pSeries;
+ ppc_md.hpte_selectslot = hpte_selectslot_pSeries;
+ ppc_md.hpte_create_valid = hpte_create_valid_pSeries;
+ ppc_md.hpte_find = hpte_find_pSeries;
+}
+
+/* Handle a fault by adding an HPTE
+ * If the address can't be determined to be valid
+ * via Linux page tables, return 1. If handled
+ * return 0
+ */
+int hash_page( unsigned long ea, unsigned long access )
+{
+ int rc = 1;
+ void * pgdir = NULL;
+ unsigned long va, vsid, vpn;
+ unsigned long newpp, hash_ind, prpn;
+ unsigned long hpteflags, regionid;
+ long slot;
+ struct mm_struct * mm;
+ pte_t old_pte, new_pte, *ptep;
+
+ /* Check for invalid addresses. */
+ if (!IS_VALID_EA(ea)) {
+ return 1;
+ }
+
+ regionid = REGION_ID(ea);
+ switch ( regionid ) {
+ case USER_REGION_ID:
+ mm = current->mm;
+ if ( mm == NULL ) {
+ PPCDBG(PPCDBG_MM, "hash_page returning; mm = 0\n");
+ return 1;
+ }
+ vsid = get_vsid(mm->context, ea );
+ break;
+ case IO_REGION_ID:
+ mm = &ioremap_mm;
+ vsid = get_kernel_vsid( ea );
+ break;
+ case VMALLOC_REGION_ID:
+ mm = &init_mm;
+ vsid = get_kernel_vsid( ea );
+ break;
+#ifdef CONFIG_PPC_EEH
+ case IO_UNMAPPED_REGION_ID:
+ udbg_printf("EEH Error ea = 0x%lx\n", ea);
+ PPCDBG_ENTER_DEBUGGER();
+ panic("EEH Error ea = 0x%lx\n", ea);
+ break;
+#endif
+ 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("Little faulted on kernel address 0x%lx\n", ea);
+ PPCDBG_ENTER_DEBUGGER();
+ panic("Little faulted on kernel address 0x%lx\n", ea);
+ break;
+ default:
+ /* Not a valid range, send the problem up to do_page_fault */
+ return 1;
+ break;
+ }
+
+ /* Search the Linux page table for a match with va */
+ va = ( vsid << 28 ) | ( ea & 0x0fffffff );
+ vpn = va >> PAGE_SHIFT;
+ pgdir = mm->pgd;
+ PPCDBG(PPCDBG_MM, "hash_page ea = 0x%16.16lx, va = 0x%16.16lx\n current = 0x%16.16lx, access = %lx\n", ea, va, current, access);
+ if ( pgdir == NULL ) {
+ return 1;
+ }
+
+ /* Lock the Linux page table to prevent mmap and kswapd
+ * from modifying entries while we search and update
+ */
+
+ spin_lock( &mm->page_table_lock );
+
+ ptep = find_linux_pte( pgdir, ea );
+ /* If no pte found, send the problem up to do_page_fault */
+ if ( ! ptep ) {
+ spin_unlock( &mm->page_table_lock );
+ return 1;
+ }
+
+ /* Acquire the hash table lock to guarantee that the linux
+ * pte we fetch will not change
+ */
+ spin_lock( &hash_table_lock );
+
+ old_pte = *ptep;
+
+ /* If the pte is not "present" (valid), send the problem
+ * up to do_page_fault.
+ */
+ if ( ! pte_present( old_pte ) ) {
+ spin_unlock( &hash_table_lock );
+ spin_unlock( &mm->page_table_lock );
+ return 1;
+ }
+
+ /* At this point we have found a pte (which was present).
+ * The spinlocks prevent this status from changing
+ * The hash_table_lock prevents the _PAGE_HASHPTE status
+ * from changing (RPN, DIRTY and ACCESSED too)
+ * The page_table_lock prevents the pte from being
+ * invalidated or modified
+ */
+
+/* At this point, we have a pte (old_pte) which can be used to build or update
+ * an HPTE. There are 5 cases:
+ *
+ * 1. There is a valid (present) pte with no associated HPTE (this is
+ * the most common case)
+ * 2. There is a valid (present) pte with an associated HPTE. The
+ * current values of the pp bits in the HPTE prevent access because the
+ * user doesn't have appropriate access rights.
+ * 3. There is a valid (present) pte with an associated HPTE. The
+ * current values of the pp bits in the HPTE prevent access because we are
+ * doing software DIRTY bit management and the page is currently not DIRTY.
+ * 4. This is a Kernel address (0xC---) for which there is no page directory.
+ * There is an HPTE for this page, but the pp bits prevent access.
+ * Since we always set up kernel pages with R/W access for the kernel
+ * this case only comes about for users trying to access the kernel.
+ * This case is always an error and is not dealt with further here.
+ * 5. This is a Kernel address (0xC---) for which there is no page directory.
+ * There is no HPTE for this page.
+
+ * Check the user's access rights to the page. If access should be prevented
+ * then send the problem up to do_page_fault.
+ */
+
+ 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 = ppc_md.hpte_find( 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 */
+ if ( access & _PAGE_RW )
+ pte_val(new_pte) |= _PAGE_ACCESSED |
+ _PAGE_DIRTY;
+ else
+ pte_val(new_pte) |= _PAGE_ACCESSED;
+
+ /* Only cases 1, 3 and 5 still in play */
+
+ newpp = computeHptePP( pte_val(new_pte) );
+
+ /* Check if pte already has an hpte (case 3) */
+ if ( pte_val(old_pte) & _PAGE_HASHPTE ) {
+ /* There MIGHT be an HPTE for this pte */
+ unsigned long hash, slot, secondary;
+ /* Local copy of first doubleword of HPTE */
+ union {
+ unsigned long d;
+ Hpte_dword0 h;
+ } hpte_dw0;
+ hash = hpt_hash(vpn, 0);
+ secondary = (pte_val(old_pte) & _PAGE_SECONDARY) >> 15;
+ if ( secondary )
+ hash = ~hash;
+ slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
+ slot += (pte_val(old_pte) & _PAGE_GROUP_IX) >> 12;
+ /* If there is an HPTE for this page it is indexed by slot */
+ hpte_dw0.d = ppc_md.hpte_getword0( slot );
+ if ( (hpte_dw0.h.avpn == (vpn >> 11) ) &&
+ (hpte_dw0.h.v) &&
+ (hpte_dw0.h.h == secondary ) ){
+ /* HPTE matches */
+ ppc_md.hpte_updatepp( slot, newpp, va );
+ if ( !pte_same( old_pte, new_pte ) )
+ *ptep = new_pte;
+ }
+ else {
+ /* HPTE is not for this pte */
+ pte_val(old_pte) &= ~_PAGE_HPTEFLAGS;
+ }
+ }
+ if ( !( pte_val(old_pte) & _PAGE_HASHPTE ) ) {
+ /* Cases 1 and 5 */
+ /* For these cases we need to create a new
+ * HPTE and update the linux pte (for
+ * case 1). For case 5 there is no linux pte.
+ *
+ * Find an available HPTE slot
+ */
+ slot = ppc_md.hpte_selectslot( vpn );
+
+ /* Debug code */
+ if ( slot == 0x8000000000000000 ) {
+ unsigned long xold_pte = pte_val(old_pte);
+ unsigned long xnew_pte = pte_val(new_pte);
+
+ udbg_printf("hash_page: ptep = 0x%016lx\n", (unsigned long)ptep );
+ udbg_printf("hash_page: old_pte = 0x%016lx\n", xold_pte );
+ udbg_printf("hash_page: new_pte = 0x%016lx\n", xnew_pte );
+ udbg_printf("hash_page: ea = 0x%016lx\n", ea );
+ udbg_printf("hash_page: va = 0x%016lx\n", va );
+ udbg_printf("hash_page: access = 0x%016lx\n", access );
+
+ panic("hash_page: hpte already exists\n");
+ }
+
+ hash_ind = 0;
+ if ( slot < 0 ) {
+ slot = -slot;
+ hash_ind = 1;
+ }
+
+ /* Set the physical address */
+ prpn = pte_val(old_pte) >> PTE_SHIFT;
+
+ if ( ptep ) {
+ /* Update the linux pte with the HPTE slot */
+ pte_val(new_pte) &= ~_PAGE_HPTEFLAGS;
+ pte_val(new_pte) |= hash_ind << 15;
+ pte_val(new_pte) |= (slot<<12) & _PAGE_GROUP_IX;
+ pte_val(new_pte) |= _PAGE_HASHPTE;
+ /* No need to use ldarx/stdcx here because all
+ * who might be updating the pte will hold the page_table_lock
+ * or the hash_table_lock (we hold both)
+ */
+ *ptep = new_pte;
+ }
+
+ /* copy appropriate flags from linux pte */
+ hpteflags = (pte_val(new_pte) & 0x1f8) | newpp;
+
+ /* Create the HPTE */
+ ppc_md.hpte_create_valid( slot, vpn, prpn, hash_ind, ptep, hpteflags, 0 );
+
+ }
+
+ /* Indicate success */
+ rc = 0;
+ }
+
+ spin_unlock( &hash_table_lock );
+ if (ptep)
+ spin_unlock( &mm->page_table_lock );
+
+ return rc;
+}
+
+void flush_hash_page( unsigned long context, unsigned long ea, pte_t pte )
+{
+ unsigned long vsid, vpn, va, hash, secondary, slot, flags;
+ /* Local copy of first doubleword of HPTE */
+ union {
+ unsigned long d;
+ Hpte_dword0 h;
+ } hpte_dw0;
+
+ if ( (ea >= USER_START ) && ( ea <= USER_END ) )
+ vsid = get_vsid( context, ea );
+ else
+ vsid = get_kernel_vsid( ea );
+ va = (vsid << 28) | (ea & 0x0fffffff);
+ vpn = va >> PAGE_SHIFT;
+ hash = hpt_hash(vpn, 0);
+ secondary = (pte_val(pte) & _PAGE_SECONDARY) >> 15;
+ if ( secondary )
+ hash = ~hash;
+ slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
+ slot += (pte_val(pte) & _PAGE_GROUP_IX) >> 12;
+ /* If there is an HPTE for this page it is indexed by slot */
+
+ spin_lock_irqsave( &hash_table_lock, flags);
+ hpte_dw0.d = ppc_md.hpte_getword0( slot );
+ if ( (hpte_dw0.h.avpn == (vpn >> 11) ) &&
+ (hpte_dw0.h.v) &&
+ (hpte_dw0.h.h == secondary ) ){
+ /* HPTE matches */
+ ppc_md.hpte_invalidate( slot );
+ }
+ else {
+ unsigned k;
+ /* Temporarily lets check for the hpte in all possible slots */
+ for ( secondary = 0; secondary < 2; ++secondary ) {
+ hash = hpt_hash(vpn, 0);
+ if ( secondary )
+ hash = ~hash;
+ slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
+ for ( k=0; k<8; ++k ) {
+ hpte_dw0.d = ppc_md.hpte_getword0( 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 );
+}
+
+int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp)
+{
+ int vleft, first=1, len, left, val;
+#define TMPBUFLEN 256
+ char buf[TMPBUFLEN], *p;
+ static const char *sizestrings[4] = {
+ "2MB", "256KB", "512KB", "1MB"
+ };
+ static const char *clockstrings[8] = {
+ "clock disabled", "+1 clock", "+1.5 clock", "reserved(3)",
+ "+2 clock", "+2.5 clock", "+3 clock", "reserved(7)"
+ };
+ static const char *typestrings[4] = {
+ "flow-through burst SRAM", "reserved SRAM",
+ "pipelined burst SRAM", "pipelined late-write SRAM"
+ };
+ static const char *holdstrings[4] = {
+ "0.5", "1.0", "(reserved2)", "(reserved3)"
+ };
+
+ if ( ((_get_PVR() >> 16) != 8) && ((_get_PVR() >> 16) != 12))
+ return -EFAULT;
+
+ if ( /*!table->maxlen ||*/ (filp->f_pos && !write)) {
+ *lenp = 0;
+ return 0;
+ }
+
+ vleft = table->maxlen / sizeof(int);
+ left = *lenp;
+
+ for (; left /*&& vleft--*/; first=0) {
+ if (write) {
+ while (left) {
+ char c;
+ if(get_user(c,(char *) buffer))
+ return -EFAULT;
+ if (!isspace(c))
+ break;
+ left--;
+ ((char *) buffer)++;
+ }
+ if (!left)
+ break;
+ len = left;
+ if (len > TMPBUFLEN-1)
+ len = TMPBUFLEN-1;
+ if(copy_from_user(buf, buffer, len))
+ return -EFAULT;
+ buf[len] = 0;
+ p = buf;
+ if (*p < '0' || *p > '9')
+ break;
+ val = simple_strtoul(p, &p, 0);
+ len = p-buf;
+ if ((len < left) && *p && !isspace(*p))
+ break;
+ buffer += len;
+ left -= len;
+#if 0
+ /* DRENG need a def */
+ _set_L2CR(0);
+ _set_L2CR(val);
+ while ( _get_L2CR() & 0x1 )
+ /* wait for invalidate to finish */;
+#endif
+
+ } else {
+ p = buf;
+ if (!first)
+ *p++ = '\t';
+#if 0
+ /* DRENG need a def */
+ val = _get_L2CR();
+#endif
+ p += sprintf(p, "0x%08x: ", val);
+ p += sprintf(p, " %s", (val >> 31) & 1 ? "enabled" :
+ "disabled");
+ p += sprintf(p, ", %sparity", (val>>30)&1 ? "" : "no ");
+ p += sprintf(p, ", %s", sizestrings[(val >> 28) & 3]);
+ p += sprintf(p, ", %s", clockstrings[(val >> 25) & 7]);
+ p += sprintf(p, ", %s", typestrings[(val >> 23) & 2]);
+ p += sprintf(p, "%s", (val>>22)&1 ? ", data only" : "");
+ p += sprintf(p, "%s", (val>>20)&1 ? ", ZZ enabled": "");
+ p += sprintf(p, ", %s", (val>>19)&1 ? "write-through" :
+ "copy-back");
+ p += sprintf(p, "%s", (val>>18)&1 ? ", testing" : "");
+ p += sprintf(p, ", %sns hold",holdstrings[(val>>16)&3]);
+ p += sprintf(p, "%s", (val>>15)&1 ? ", DLL slow" : "");
+ p += sprintf(p, "%s", (val>>14)&1 ? ", diff clock" :"");
+ p += sprintf(p, "%s", (val>>13)&1 ? ", DLL bypass" :"");
+
+ p += sprintf(p,"\n");
+
+ len = strlen(buf);
+ if (len > left)
+ len = left;
+ if(copy_to_user(buffer, buf, len))
+ return -EFAULT;
+ left -= len;
+ buffer += len;
+ break;
+ }
+ }
+
+ if (!write && !first && left) {
+ if(put_user('\n', (char *) buffer))
+ return -EFAULT;
+ left--, buffer++;
+ }
+ if (write) {
+ p = (char *) buffer;
+ while (left) {
+ char c;
+ if(get_user(c, p++))
+ return -EFAULT;
+ if (!isspace(c))
+ break;
+ left--;
+ }
+ }
+ if (write && first)
+ return -EINVAL;
+ *lenp -= left;
+ filp->f_pos += *lenp;
+ return 0;
+}
+
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/hvCall.S linuxppc64_2_4/arch/ppc64/kernel/hvCall.S
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/hvCall.S Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/hvCall.S Thu Jul 19 14:02:55 2001
@@ -0,0 +1,99 @@
+/*
+ * arch/ppc64/kernel/hvCall.S
+ *
+ *
+ * This file contains the code to perform calls to the
+ * iSeries LPAR hypervisor
+ *
+ * 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.
+ */
+
+#include "ppc_asm.h"
+#include
+#include
+
+ .text
+
+/*
+ * Hypervisor call
+ *
+ * Invoke the iSeries hypervisor via the System Call instruction
+ * Parameters are passed to this routine in registers r3 - r10
+ *
+ * r3 contains the HV function to be called
+ * r4-r10 contain the operands to the hypervisor function
+ *
+ */
+
+_GLOBAL(HvCall)
+_GLOBAL(HvCall0)
+_GLOBAL(HvCall1)
+_GLOBAL(HvCall2)
+_GLOBAL(HvCall3)
+_GLOBAL(HvCall4)
+_GLOBAL(HvCall5)
+_GLOBAL(HvCall6)
+_GLOBAL(HvCall7)
+
+
+ mfcr r0
+ std r0,-8(r1)
+ stdu r1,-(STACK_FRAME_OVERHEAD+16)(r1)
+
+ /* r0 = 0xffffffffffffffff indicates a hypervisor call */
+
+ li r0,-1
+
+ /* Invoke the hypervisor */
+
+ sc
+
+ ld r1,0(r1)
+ ld r0,-8(r1)
+ mtcrf 0xff,r0
+
+ /* return to caller, return value in r3 */
+
+ blr
+
+_GLOBAL(HvCall0Ret16)
+_GLOBAL(HvCall1Ret16)
+_GLOBAL(HvCall2Ret16)
+_GLOBAL(HvCall3Ret16)
+_GLOBAL(HvCall4Ret16)
+_GLOBAL(HvCall5Ret16)
+_GLOBAL(HvCall6Ret16)
+_GLOBAL(HvCall7Ret16)
+
+ mfcr r0
+ std r0,-8(r1)
+ std r31,-16(r1)
+ stdu r1,-(STACK_FRAME_OVERHEAD+32)(r1)
+
+ mr r31,r4
+ li r0,-1
+ mr r4,r5
+ mr r5,r6
+ mr r6,r7
+ mr r7,r8
+ mr r8,r9
+ mr r9,r10
+
+ sc
+
+ std r3,0(r31)
+ std r4,8(r31)
+
+ mr r3,r5
+
+ ld r1,0(r1)
+ ld r0,-8(r1)
+ mtcrf 0xff,r0
+ ld r31,-16(r1)
+
+ blr
+
+
diff -uNr --exclude=CVS /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/i8259.c linuxppc64_2_4/arch/ppc64/kernel/i8259.c
--- /kernels/64/linux-2.4.18-rc3/arch/ppc64/kernel/i8259.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/i8259.c Tue Oct 9 21:22:29 2001
@@ -0,0 +1,164 @@
+/*
+ * c 2001 PPC64 Team, IBM Corp
+ *
+ * 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.
+ */
+#include
+#include
+#include
+#include
+#include