Merge with rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
This commit is contained in:
commit
1d4ae4a119
|
@ -239,9 +239,9 @@ X!Ilib/string.c
|
|||
<title>Network device support</title>
|
||||
<sect1><title>Driver Support</title>
|
||||
!Enet/core/dev.c
|
||||
</sect1>
|
||||
<sect1><title>8390 Based Network Cards</title>
|
||||
!Edrivers/net/8390.c
|
||||
!Enet/ethernet/eth.c
|
||||
!Einclude/linux/etherdevice.h
|
||||
!Enet/core/wireless.c
|
||||
</sect1>
|
||||
<sect1><title>Synchronous PPP</title>
|
||||
!Edrivers/net/wan/syncppp.c
|
||||
|
|
|
@ -8,10 +8,9 @@ Compilation of kernel
|
|||
---------------------
|
||||
|
||||
In order to compile ARM Linux, you will need a compiler capable of
|
||||
generating ARM ELF code with GNU extensions. GCC 2.95.1, EGCS
|
||||
1.1.2, and GCC 3.3 are known to be good compilers. Fortunately, you
|
||||
needn't guess. The kernel will report an error if your compiler is
|
||||
a recognized offender.
|
||||
generating ARM ELF code with GNU extensions. GCC 3.3 is known to be
|
||||
a good compiler. Fortunately, you needn't guess. The kernel will report
|
||||
an error if your compiler is a recognized offender.
|
||||
|
||||
To build ARM Linux natively, you shouldn't have to alter the ARCH = line
|
||||
in the top level Makefile. However, if you don't have the ARM Linux ELF
|
||||
|
|
|
@ -1,48 +1,153 @@
|
|||
S2IO Technologies XFrame 10 Gig adapter.
|
||||
-------------------------------------------
|
||||
Release notes for Neterion's (Formerly S2io) Xframe I/II PCI-X 10GbE driver.
|
||||
|
||||
I. Module loadable parameters.
|
||||
When loaded as a module, the driver provides a host of Module loadable
|
||||
parameters, so the device can be tuned as per the users needs.
|
||||
A list of the Module params is given below.
|
||||
(i) ring_num: This can be used to program the number of
|
||||
receive rings used in the driver.
|
||||
(ii) ring_len: This defines the number of descriptors each ring
|
||||
can have. There can be a maximum of 8 rings.
|
||||
(iii) frame_len: This is an array of size 8. Using this we can
|
||||
set the maximum size of the received frame that can
|
||||
be steered into the corrsponding receive ring.
|
||||
(iv) fifo_num: This defines the number of Tx FIFOs thats used in
|
||||
the driver.
|
||||
(v) fifo_len: Each element defines the number of
|
||||
Tx descriptors that can be associated with each
|
||||
corresponding FIFO. There are a maximum of 8 FIFOs.
|
||||
(vi) tx_prio: This is a bool, if module is loaded with a non-zero
|
||||
value for tx_prio multi FIFO scheme is activated.
|
||||
(vii) rx_prio: This is a bool, if module is loaded with a non-zero
|
||||
value for tx_prio multi RING scheme is activated.
|
||||
(viii) latency_timer: The value given against this param will be
|
||||
loaded into the latency timer register in PCI Config
|
||||
space, else the register is left with its reset value.
|
||||
Contents
|
||||
=======
|
||||
- 1. Introduction
|
||||
- 2. Identifying the adapter/interface
|
||||
- 3. Features supported
|
||||
- 4. Command line parameters
|
||||
- 5. Performance suggestions
|
||||
- 6. Available Downloads
|
||||
|
||||
II. Performance tuning.
|
||||
By changing a few sysctl parameters.
|
||||
Copy the following lines into a file and run the following command,
|
||||
"sysctl -p <file_name>"
|
||||
### IPV4 specific settings
|
||||
net.ipv4.tcp_timestamps = 0 # turns TCP timestamp support off, default 1, reduces CPU use
|
||||
net.ipv4.tcp_sack = 0 # turn SACK support off, default on
|
||||
# on systems with a VERY fast bus -> memory interface this is the big gainer
|
||||
net.ipv4.tcp_rmem = 10000000 10000000 10000000 # sets min/default/max TCP read buffer, default 4096 87380 174760
|
||||
net.ipv4.tcp_wmem = 10000000 10000000 10000000 # sets min/pressure/max TCP write buffer, default 4096 16384 131072
|
||||
net.ipv4.tcp_mem = 10000000 10000000 10000000 # sets min/pressure/max TCP buffer space, default 31744 32256 32768
|
||||
|
||||
### CORE settings (mostly for socket and UDP effect)
|
||||
net.core.rmem_max = 524287 # maximum receive socket buffer size, default 131071
|
||||
net.core.wmem_max = 524287 # maximum send socket buffer size, default 131071
|
||||
net.core.rmem_default = 524287 # default receive socket buffer size, default 65535
|
||||
net.core.wmem_default = 524287 # default send socket buffer size, default 65535
|
||||
net.core.optmem_max = 524287 # maximum amount of option memory buffers, default 10240
|
||||
net.core.netdev_max_backlog = 300000 # number of unprocessed input packets before kernel starts dropping them, default 300
|
||||
---End of performance tuning file---
|
||||
|
||||
1. Introduction:
|
||||
This Linux driver supports Neterion's Xframe I PCI-X 1.0 and
|
||||
Xframe II PCI-X 2.0 adapters. It supports several features
|
||||
such as jumbo frames, MSI/MSI-X, checksum offloads, TSO, UFO and so on.
|
||||
See below for complete list of features.
|
||||
All features are supported for both IPv4 and IPv6.
|
||||
|
||||
2. Identifying the adapter/interface:
|
||||
a. Insert the adapter(s) in your system.
|
||||
b. Build and load driver
|
||||
# insmod s2io.ko
|
||||
c. View log messages
|
||||
# dmesg | tail -40
|
||||
You will see messages similar to:
|
||||
eth3: Neterion Xframe I 10GbE adapter (rev 3), Version 2.0.9.1, Intr type INTA
|
||||
eth4: Neterion Xframe II 10GbE adapter (rev 2), Version 2.0.9.1, Intr type INTA
|
||||
eth4: Device is on 64 bit 133MHz PCIX(M1) bus
|
||||
|
||||
The above messages identify the adapter type(Xframe I/II), adapter revision,
|
||||
driver version, interface name(eth3, eth4), Interrupt type(INTA, MSI, MSI-X).
|
||||
In case of Xframe II, the PCI/PCI-X bus width and frequency are displayed
|
||||
as well.
|
||||
|
||||
To associate an interface with a physical adapter use "ethtool -p <ethX>".
|
||||
The corresponding adapter's LED will blink multiple times.
|
||||
|
||||
3. Features supported:
|
||||
a. Jumbo frames. Xframe I/II supports MTU upto 9600 bytes,
|
||||
modifiable using ifconfig command.
|
||||
|
||||
b. Offloads. Supports checksum offload(TCP/UDP/IP) on transmit
|
||||
and receive, TSO.
|
||||
|
||||
c. Multi-buffer receive mode. Scattering of packet across multiple
|
||||
buffers. Currently driver supports 2-buffer mode which yields
|
||||
significant performance improvement on certain platforms(SGI Altix,
|
||||
IBM xSeries).
|
||||
|
||||
d. MSI/MSI-X. Can be enabled on platforms which support this feature
|
||||
(IA64, Xeon) resulting in noticeable performance improvement(upto 7%
|
||||
on certain platforms).
|
||||
|
||||
e. NAPI. Compile-time option(CONFIG_S2IO_NAPI) for better Rx interrupt
|
||||
moderation.
|
||||
|
||||
f. Statistics. Comprehensive MAC-level and software statistics displayed
|
||||
using "ethtool -S" option.
|
||||
|
||||
g. Multi-FIFO/Ring. Supports up to 8 transmit queues and receive rings,
|
||||
with multiple steering options.
|
||||
|
||||
4. Command line parameters
|
||||
a. tx_fifo_num
|
||||
Number of transmit queues
|
||||
Valid range: 1-8
|
||||
Default: 1
|
||||
|
||||
b. rx_ring_num
|
||||
Number of receive rings
|
||||
Valid range: 1-8
|
||||
Default: 1
|
||||
|
||||
c. tx_fifo_len
|
||||
Size of each transmit queue
|
||||
Valid range: Total length of all queues should not exceed 8192
|
||||
Default: 4096
|
||||
|
||||
d. rx_ring_sz
|
||||
Size of each receive ring(in 4K blocks)
|
||||
Valid range: Limited by memory on system
|
||||
Default: 30
|
||||
|
||||
e. intr_type
|
||||
Specifies interrupt type. Possible values 1(INTA), 2(MSI), 3(MSI-X)
|
||||
Valid range: 1-3
|
||||
Default: 1
|
||||
|
||||
5. Performance suggestions
|
||||
General:
|
||||
a. Set MTU to maximum(9000 for switch setup, 9600 in back-to-back configuration)
|
||||
b. Set TCP windows size to optimal value.
|
||||
For instance, for MTU=1500 a value of 210K has been observed to result in
|
||||
good performance.
|
||||
# sysctl -w net.ipv4.tcp_rmem="210000 210000 210000"
|
||||
# sysctl -w net.ipv4.tcp_wmem="210000 210000 210000"
|
||||
For MTU=9000, TCP window size of 10 MB is recommended.
|
||||
# sysctl -w net.ipv4.tcp_rmem="10000000 10000000 10000000"
|
||||
# sysctl -w net.ipv4.tcp_wmem="10000000 10000000 10000000"
|
||||
|
||||
Transmit performance:
|
||||
a. By default, the driver respects BIOS settings for PCI bus parameters.
|
||||
However, you may want to experiment with PCI bus parameters
|
||||
max-split-transactions(MOST) and MMRBC (use setpci command).
|
||||
A MOST value of 2 has been found optimal for Opterons and 3 for Itanium.
|
||||
It could be different for your hardware.
|
||||
Set MMRBC to 4K**.
|
||||
|
||||
For example you can set
|
||||
For opteron
|
||||
#setpci -d 17d5:* 62=1d
|
||||
For Itanium
|
||||
#setpci -d 17d5:* 62=3d
|
||||
|
||||
For detailed description of the PCI registers, please see Xframe User Guide.
|
||||
|
||||
b. Ensure Transmit Checksum offload is enabled. Use ethtool to set/verify this
|
||||
parameter.
|
||||
c. Turn on TSO(using "ethtool -K")
|
||||
# ethtool -K <ethX> tso on
|
||||
|
||||
Receive performance:
|
||||
a. By default, the driver respects BIOS settings for PCI bus parameters.
|
||||
However, you may want to set PCI latency timer to 248.
|
||||
#setpci -d 17d5:* LATENCY_TIMER=f8
|
||||
For detailed description of the PCI registers, please see Xframe User Guide.
|
||||
b. Use 2-buffer mode. This results in large performance boost on
|
||||
on certain platforms(eg. SGI Altix, IBM xSeries).
|
||||
c. Ensure Receive Checksum offload is enabled. Use "ethtool -K ethX" command to
|
||||
set/verify this option.
|
||||
d. Enable NAPI feature(in kernel configuration Device Drivers ---> Network
|
||||
device support ---> Ethernet (10000 Mbit) ---> S2IO 10Gbe Xframe NIC) to
|
||||
bring down CPU utilization.
|
||||
|
||||
** For AMD opteron platforms with 8131 chipset, MMRBC=1 and MOST=1 are
|
||||
recommended as safe parameters.
|
||||
For more information, please review the AMD8131 errata at
|
||||
http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/26310.pdf
|
||||
|
||||
6. Available Downloads
|
||||
Neterion "s2io" driver in Red Hat and Suse 2.6-based distributions is kept up
|
||||
to date, also the latest "s2io" code (including support for 2.4 kernels) is
|
||||
available via "Support" link on the Neterion site: http://www.neterion.com.
|
||||
|
||||
For Xframe User Guide (Programming manual), visit ftp site ns1.s2io.com,
|
||||
user: linuxdocs password: HALdocs
|
||||
|
||||
7. Support
|
||||
For further support please contact either your 10GbE Xframe NIC vendor (IBM,
|
||||
HP, SGI etc.) or click on the "Support" link on the Neterion site:
|
||||
http://www.neterion.com.
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
Copyright (c) 2003-2005 QLogic Corporation
|
||||
QLogic Linux Fibre Channel HBA Driver
|
||||
|
||||
This program includes a device driver for Linux 2.6 that may be
|
||||
distributed with QLogic hardware specific firmware binary file.
|
||||
You may modify and redistribute the device driver code under the
|
||||
GNU General Public License as published by the Free Software
|
||||
Foundation (version 2 or a later version).
|
||||
|
||||
You may redistribute the hardware specific firmware binary file
|
||||
under the following terms:
|
||||
|
||||
1. Redistribution of source code (only if applicable),
|
||||
must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer.
|
||||
|
||||
2. Redistribution in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
3. The name of QLogic Corporation may not be used to
|
||||
endorse or promote products derived from this software
|
||||
without specific prior written permission
|
||||
|
||||
REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE,
|
||||
THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT
|
||||
CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR
|
||||
OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT,
|
||||
TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN
|
||||
ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN
|
||||
COMBINATION WITH THIS PROGRAM.
|
14
MAINTAINERS
14
MAINTAINERS
|
@ -297,6 +297,11 @@ P: Richard Purdie
|
|||
M: rpurdie@rpsys.net
|
||||
S: Maintained
|
||||
|
||||
ARM/TOSA MACHINE SUPPORT
|
||||
P: Dirk Opfer
|
||||
M: dirk@opfer-online.de
|
||||
S: Maintained
|
||||
|
||||
ARM/PLEB SUPPORT
|
||||
P: Peter Chubb
|
||||
M: pleb@gelato.unsw.edu.au
|
||||
|
@ -910,6 +915,15 @@ L: linux-fbdev-devel@lists.sourceforge.net
|
|||
W: http://linux-fbdev.sourceforge.net/
|
||||
S: Maintained
|
||||
|
||||
FREESCALE SOC FS_ENET DRIVER
|
||||
P: Pantelis Antoniou
|
||||
M: pantelis.antoniou@gmail.com
|
||||
P: Vitaly Bordug
|
||||
M: vbordug@ru.mvista.com
|
||||
L: linuxppc-embedded@ozlabs.org
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
FILE LOCKING (flock() and fcntl()/lockf())
|
||||
P: Matthew Wilcox
|
||||
M: matthew@wil.cx
|
||||
|
|
8
Makefile
8
Makefile
|
@ -346,7 +346,8 @@ AFLAGS_KERNEL =
|
|||
# Use LINUXINCLUDE when you must reference the include/ directory.
|
||||
# Needed to be compatible with the O= option
|
||||
LINUXINCLUDE := -Iinclude \
|
||||
$(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include)
|
||||
$(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
|
||||
-imacros include/linux/autoconf.h
|
||||
|
||||
CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
|
||||
|
||||
|
@ -1249,11 +1250,6 @@ tags: FORCE
|
|||
# Scripts to check various things for consistency
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
configcheck:
|
||||
find * $(RCS_FIND_IGNORE) \
|
||||
-name '*.[hcS]' -type f -print | sort \
|
||||
| xargs $(PERL) -w scripts/checkconfig.pl
|
||||
|
||||
includecheck:
|
||||
find * $(RCS_FIND_IGNORE) \
|
||||
-name '*.[hcS]' -type f -print | sort \
|
||||
|
|
|
@ -704,8 +704,7 @@ source "drivers/acorn/block/Kconfig"
|
|||
|
||||
if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \
|
||||
|| ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
|
||||
|| ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
|
||||
|| MACH_MP1000
|
||||
|| ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
|
||||
source "drivers/ide/Kconfig"
|
||||
endif
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ comma = ,
|
|||
# macro, but instead defines a whole series of macros which makes
|
||||
# testing for a specific architecture or later rather impossible.
|
||||
arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
|
||||
arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
|
||||
arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4)
|
||||
arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4
|
||||
arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3
|
||||
|
@ -143,7 +144,7 @@ drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
|
|||
drivers-$(CONFIG_ARCH_CLPS7500) += drivers/acorn/char/
|
||||
drivers-$(CONFIG_ARCH_L7200) += drivers/acorn/char/
|
||||
|
||||
libs-y += arch/arm/lib/
|
||||
libs-y := arch/arm/lib/ $(libs-y)
|
||||
|
||||
# Default target when executing plain make
|
||||
ifeq ($(CONFIG_XIP_KERNEL),y)
|
||||
|
|
|
@ -39,8 +39,7 @@
|
|||
defined(CONFIG_ARCH_IXP4XX) || \
|
||||
defined(CONFIG_ARCH_IXP2000) || \
|
||||
defined(CONFIG_ARCH_LH7A40X) || \
|
||||
defined(CONFIG_ARCH_OMAP) || \
|
||||
defined(CONFIG_MACH_MP1000)
|
||||
defined(CONFIG_ARCH_OMAP)
|
||||
.macro loadsp, rb
|
||||
addruart \rb
|
||||
.endm
|
||||
|
|
|
@ -152,7 +152,7 @@ CONFIG_ALIGNMENT_TRAP=y
|
|||
#
|
||||
CONFIG_ZBOOT_ROM_TEXT=0x0
|
||||
CONFIG_ZBOOT_ROM_BSS=0x0
|
||||
CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
|
||||
CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
|
||||
# CONFIG_XIP_KERNEL is not set
|
||||
|
||||
#
|
||||
|
@ -560,7 +560,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
|
|||
#
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=2
|
||||
CONFIG_SERIAL_8250_NR_UARTS=3
|
||||
# CONFIG_SERIAL_8250_EXTENDED is not set
|
||||
|
||||
#
|
||||
|
|
|
@ -560,7 +560,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
|
|||
#
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=2
|
||||
CONFIG_SERIAL_8250_NR_UARTS=3
|
||||
# CONFIG_SERIAL_8250_EXTENDED is not set
|
||||
|
||||
#
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.14-rc1
|
||||
# Fri Sep 16 15:48:13 2005
|
||||
# Linux kernel version: 2.6.14-rc2
|
||||
# Thu Sep 29 14:50:10 2005
|
||||
#
|
||||
CONFIG_ARM=y
|
||||
CONFIG_MMU=y
|
||||
|
@ -12,11 +12,9 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
|
|||
#
|
||||
# Code maturity level options
|
||||
#
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
# CONFIG_CLEAN_COMPILE is not set
|
||||
CONFIG_BROKEN=y
|
||||
# CONFIG_EXPERIMENTAL is not set
|
||||
CONFIG_CLEAN_COMPILE=y
|
||||
CONFIG_BROKEN_ON_SMP=y
|
||||
CONFIG_LOCK_KERNEL=y
|
||||
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||
|
||||
#
|
||||
|
@ -24,18 +22,16 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
|
|||
#
|
||||
CONFIG_LOCALVERSION=""
|
||||
CONFIG_LOCALVERSION_AUTO=y
|
||||
CONFIG_SWAP=y
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_SYSVIPC=y
|
||||
# CONFIG_POSIX_MQUEUE is not set
|
||||
# CONFIG_BSD_PROCESS_ACCT is not set
|
||||
CONFIG_SYSCTL=y
|
||||
# CONFIG_AUDIT is not set
|
||||
# CONFIG_HOTPLUG is not set
|
||||
CONFIG_HOTPLUG=y
|
||||
CONFIG_KOBJECT_UEVENT=y
|
||||
CONFIG_IKCONFIG=y
|
||||
CONFIG_IKCONFIG_PROC=y
|
||||
# CONFIG_IKCONFIG is not set
|
||||
CONFIG_INITRAMFS_SOURCE=""
|
||||
CONFIG_EMBEDDED=y
|
||||
# CONFIG_EMBEDDED is not set
|
||||
CONFIG_KALLSYMS=y
|
||||
# CONFIG_KALLSYMS_ALL is not set
|
||||
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
||||
|
@ -58,17 +54,15 @@ CONFIG_BASE_SMALL=0
|
|||
#
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
# CONFIG_MODULE_FORCE_UNLOAD is not set
|
||||
CONFIG_OBSOLETE_MODPARM=y
|
||||
# CONFIG_MODVERSIONS is not set
|
||||
# CONFIG_MODULE_SRCVERSION_ALL is not set
|
||||
CONFIG_KMOD=y
|
||||
# CONFIG_KMOD is not set
|
||||
|
||||
#
|
||||
# System Type
|
||||
#
|
||||
# CONFIG_ARCH_CLPS7500 is not set
|
||||
CONFIG_ARCH_CLPS711X=y
|
||||
# CONFIG_ARCH_CLPS711X is not set
|
||||
# CONFIG_ARCH_CO285 is not set
|
||||
# CONFIG_ARCH_EBSA110 is not set
|
||||
# CONFIG_ARCH_CAMELOT is not set
|
||||
|
@ -86,43 +80,43 @@ CONFIG_ARCH_CLPS711X=y
|
|||
# CONFIG_ARCH_LH7A40X is not set
|
||||
# CONFIG_ARCH_OMAP is not set
|
||||
# CONFIG_ARCH_VERSATILE is not set
|
||||
CONFIG_ARCH_REALVIEW=y
|
||||
# CONFIG_ARCH_IMX is not set
|
||||
# CONFIG_ARCH_H720X is not set
|
||||
# CONFIG_ARCH_AAEC2000 is not set
|
||||
|
||||
#
|
||||
# CLPS711X/EP721X Implementations
|
||||
# RealView platform type
|
||||
#
|
||||
# CONFIG_ARCH_AUTCPU12 is not set
|
||||
# CONFIG_ARCH_CDB89712 is not set
|
||||
# CONFIG_ARCH_CEIVA is not set
|
||||
# CONFIG_ARCH_CLEP7312 is not set
|
||||
# CONFIG_ARCH_EDB7211 is not set
|
||||
# CONFIG_ARCH_P720T is not set
|
||||
# CONFIG_ARCH_FORTUNET is not set
|
||||
CONFIG_MACH_MP1000=y
|
||||
CONFIG_MP1000_90MHZ=y
|
||||
CONFIG_MACH_REALVIEW_EB=y
|
||||
|
||||
#
|
||||
# Processor Type
|
||||
#
|
||||
CONFIG_CPU_32=y
|
||||
CONFIG_CPU_ARM720T=y
|
||||
CONFIG_CPU_32v4=y
|
||||
CONFIG_CPU_ABRT_LV4T=y
|
||||
CONFIG_CPU_CACHE_V4=y
|
||||
CONFIG_CPU_ARM926T=y
|
||||
# CONFIG_CPU_V6 is not set
|
||||
CONFIG_CPU_32v5=y
|
||||
CONFIG_CPU_ABRT_EV5TJ=y
|
||||
CONFIG_CPU_CACHE_VIVT=y
|
||||
CONFIG_CPU_COPY_V4WT=y
|
||||
CONFIG_CPU_TLB_V4WT=y
|
||||
CONFIG_CPU_COPY_V4WB=y
|
||||
CONFIG_CPU_TLB_V4WBI=y
|
||||
|
||||
#
|
||||
# Processor Features
|
||||
#
|
||||
CONFIG_ARM_THUMB=y
|
||||
# CONFIG_CPU_ICACHE_DISABLE is not set
|
||||
# CONFIG_CPU_DCACHE_DISABLE is not set
|
||||
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
|
||||
# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
|
||||
CONFIG_ARM_GIC=y
|
||||
CONFIG_ICST307=y
|
||||
|
||||
#
|
||||
# Bus support
|
||||
#
|
||||
CONFIG_ARM_AMBA=y
|
||||
CONFIG_ISA_DMA_API=y
|
||||
|
||||
#
|
||||
|
@ -133,14 +127,8 @@ CONFIG_ISA_DMA_API=y
|
|||
#
|
||||
# Kernel Features
|
||||
#
|
||||
# CONFIG_SMP is not set
|
||||
CONFIG_PREEMPT=y
|
||||
# CONFIG_NO_IDLE_HZ is not set
|
||||
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
|
||||
CONFIG_SELECT_MEMORY_MODEL=y
|
||||
CONFIG_FLATMEM_MANUAL=y
|
||||
# CONFIG_DISCONTIGMEM_MANUAL is not set
|
||||
# CONFIG_SPARSEMEM_MANUAL is not set
|
||||
CONFIG_FLATMEM=y
|
||||
CONFIG_FLAT_NODE_MEM_MAP=y
|
||||
# CONFIG_SPARSEMEM_STATIC is not set
|
||||
|
@ -151,7 +139,7 @@ CONFIG_ALIGNMENT_TRAP=y
|
|||
#
|
||||
CONFIG_ZBOOT_ROM_TEXT=0x0
|
||||
CONFIG_ZBOOT_ROM_BSS=0x0
|
||||
CONFIG_CMDLINE="console=ttyCL,38400 root=/dev/discs/disc0/part1 ip=any cs89x0_media=rj45"
|
||||
CONFIG_CMDLINE="root=/dev/nfs nfsroot=10.1.69.3:/work/nfsroot ip=dhcp console=ttyAMA0 mem=128M"
|
||||
# CONFIG_XIP_KERNEL is not set
|
||||
|
||||
#
|
||||
|
@ -163,14 +151,14 @@ CONFIG_CMDLINE="console=ttyCL,38400 root=/dev/discs/disc0/part1 ip=any cs89x0_me
|
|||
#
|
||||
CONFIG_FPE_NWFPE=y
|
||||
# CONFIG_FPE_NWFPE_XP is not set
|
||||
# CONFIG_FPE_FASTFPE is not set
|
||||
# CONFIG_VFP is not set
|
||||
|
||||
#
|
||||
# Userspace binary formats
|
||||
#
|
||||
CONFIG_BINFMT_ELF=y
|
||||
# CONFIG_BINFMT_AOUT is not set
|
||||
CONFIG_BINFMT_MISC=y
|
||||
# CONFIG_BINFMT_MISC is not set
|
||||
# CONFIG_ARTHUR is not set
|
||||
|
||||
#
|
||||
|
@ -197,10 +185,9 @@ CONFIG_IP_FIB_HASH=y
|
|||
CONFIG_IP_PNP=y
|
||||
CONFIG_IP_PNP_DHCP=y
|
||||
CONFIG_IP_PNP_BOOTP=y
|
||||
CONFIG_IP_PNP_RARP=y
|
||||
# CONFIG_IP_PNP_RARP is not set
|
||||
# CONFIG_NET_IPIP is not set
|
||||
# CONFIG_NET_IPGRE is not set
|
||||
# CONFIG_ARPD is not set
|
||||
# CONFIG_SYN_COOKIES is not set
|
||||
# CONFIG_INET_AH is not set
|
||||
# CONFIG_INET_ESP is not set
|
||||
|
@ -210,36 +197,14 @@ CONFIG_INET_DIAG=y
|
|||
CONFIG_INET_TCP_DIAG=y
|
||||
# CONFIG_TCP_CONG_ADVANCED is not set
|
||||
CONFIG_TCP_CONG_BIC=y
|
||||
CONFIG_IPV6=y
|
||||
# CONFIG_IPV6_PRIVACY is not set
|
||||
# CONFIG_INET6_AH is not set
|
||||
# CONFIG_INET6_ESP is not set
|
||||
# CONFIG_INET6_IPCOMP is not set
|
||||
# CONFIG_INET6_TUNNEL is not set
|
||||
# CONFIG_IPV6_TUNNEL is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
# CONFIG_NETFILTER is not set
|
||||
|
||||
#
|
||||
# DCCP Configuration (EXPERIMENTAL)
|
||||
#
|
||||
# CONFIG_IP_DCCP is not set
|
||||
|
||||
#
|
||||
# SCTP Configuration (EXPERIMENTAL)
|
||||
#
|
||||
# CONFIG_IP_SCTP is not set
|
||||
# CONFIG_ATM is not set
|
||||
# CONFIG_BRIDGE is not set
|
||||
# CONFIG_VLAN_8021Q is not set
|
||||
# CONFIG_DECNET is not set
|
||||
# CONFIG_LLC2 is not set
|
||||
# CONFIG_IPX is not set
|
||||
# CONFIG_ATALK is not set
|
||||
# CONFIG_X25 is not set
|
||||
# CONFIG_LAPB is not set
|
||||
# CONFIG_NET_DIVERT is not set
|
||||
# CONFIG_ECONET is not set
|
||||
# CONFIG_WAN_ROUTER is not set
|
||||
# CONFIG_NET_SCHED is not set
|
||||
# CONFIG_NET_CLS_ROUTE is not set
|
||||
|
||||
|
@ -247,7 +212,6 @@ CONFIG_IPV6=y
|
|||
# Network testing
|
||||
#
|
||||
# CONFIG_NET_PKTGEN is not set
|
||||
# CONFIG_NETFILTER_NETLINK is not set
|
||||
# CONFIG_HAMRADIO is not set
|
||||
# CONFIG_IRDA is not set
|
||||
# CONFIG_BT is not set
|
||||
|
@ -269,14 +233,10 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
|
|||
# Memory Technology Devices (MTD)
|
||||
#
|
||||
CONFIG_MTD=y
|
||||
CONFIG_MTD_DEBUG=y
|
||||
CONFIG_MTD_DEBUG_VERBOSE=3
|
||||
# CONFIG_MTD_DEBUG is not set
|
||||
# CONFIG_MTD_CONCAT is not set
|
||||
CONFIG_MTD_PARTITIONS=y
|
||||
CONFIG_MTD_REDBOOT_PARTS=m
|
||||
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2
|
||||
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
|
||||
# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
|
||||
# CONFIG_MTD_REDBOOT_PARTS is not set
|
||||
CONFIG_MTD_CMDLINE_PARTS=y
|
||||
# CONFIG_MTD_AFS_PARTS is not set
|
||||
|
||||
|
@ -292,45 +252,36 @@ CONFIG_MTD_BLOCK=y
|
|||
#
|
||||
# RAM/ROM/Flash chip drivers
|
||||
#
|
||||
CONFIG_MTD_CFI=m
|
||||
CONFIG_MTD_CFI=y
|
||||
# CONFIG_MTD_JEDECPROBE is not set
|
||||
CONFIG_MTD_GEN_PROBE=m
|
||||
CONFIG_MTD_CFI_ADV_OPTIONS=y
|
||||
CONFIG_MTD_CFI_NOSWAP=y
|
||||
# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
|
||||
# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
|
||||
CONFIG_MTD_CFI_GEOMETRY=y
|
||||
# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
|
||||
# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set
|
||||
CONFIG_MTD_GEN_PROBE=y
|
||||
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
|
||||
CONFIG_MTD_MAP_BANK_WIDTH_1=y
|
||||
CONFIG_MTD_MAP_BANK_WIDTH_2=y
|
||||
CONFIG_MTD_MAP_BANK_WIDTH_4=y
|
||||
# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
|
||||
# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
|
||||
# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
|
||||
# CONFIG_MTD_CFI_I1 is not set
|
||||
CONFIG_MTD_CFI_I1=y
|
||||
CONFIG_MTD_CFI_I2=y
|
||||
# CONFIG_MTD_CFI_I4 is not set
|
||||
# CONFIG_MTD_CFI_I8 is not set
|
||||
# CONFIG_MTD_OTP is not set
|
||||
CONFIG_MTD_CFI_INTELEXT=m
|
||||
# CONFIG_MTD_CFI_AMDSTD is not set
|
||||
CONFIG_MTD_CFI_INTELEXT=y
|
||||
CONFIG_MTD_CFI_AMDSTD=y
|
||||
CONFIG_MTD_CFI_AMDSTD_RETRY=0
|
||||
# CONFIG_MTD_CFI_STAA is not set
|
||||
CONFIG_MTD_CFI_UTIL=m
|
||||
CONFIG_MTD_CFI_UTIL=y
|
||||
# CONFIG_MTD_RAM is not set
|
||||
# CONFIG_MTD_ROM is not set
|
||||
# CONFIG_MTD_ABSENT is not set
|
||||
# CONFIG_MTD_OBSOLETE_CHIPS is not set
|
||||
# CONFIG_MTD_XIP is not set
|
||||
|
||||
#
|
||||
# Mapping drivers for chip access
|
||||
#
|
||||
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
|
||||
CONFIG_MTD_PHYSMAP=m
|
||||
CONFIG_MTD_PHYSMAP_START=0x0000000
|
||||
CONFIG_MTD_PHYSMAP_LEN=0x4000000
|
||||
CONFIG_MTD_PHYSMAP_BANKWIDTH=2
|
||||
# CONFIG_MTD_ARM_INTEGRATOR is not set
|
||||
CONFIG_MTD_EDB7312=m
|
||||
# CONFIG_MTD_PHYSMAP is not set
|
||||
CONFIG_MTD_ARM_INTEGRATOR=y
|
||||
# CONFIG_MTD_EDB7312 is not set
|
||||
# CONFIG_MTD_PLATRAM is not set
|
||||
|
||||
#
|
||||
|
@ -340,7 +291,6 @@ CONFIG_MTD_EDB7312=m
|
|||
# CONFIG_MTD_PHRAM is not set
|
||||
# CONFIG_MTD_MTDRAM is not set
|
||||
# CONFIG_MTD_BLKMTD is not set
|
||||
# CONFIG_MTD_BLOCK2MTD is not set
|
||||
|
||||
#
|
||||
# Disk-On-Chip Device Drivers
|
||||
|
@ -352,12 +302,7 @@ CONFIG_MTD_EDB7312=m
|
|||
#
|
||||
# NAND Flash Device Drivers
|
||||
#
|
||||
CONFIG_MTD_NAND=y
|
||||
# CONFIG_MTD_NAND_VERIFY_WRITE is not set
|
||||
CONFIG_MTD_NAND_MP1000=y
|
||||
CONFIG_MTD_NAND_IDS=y
|
||||
# CONFIG_MTD_NAND_DISKONCHIP is not set
|
||||
# CONFIG_MTD_NAND_NANDSIM is not set
|
||||
# CONFIG_MTD_NAND is not set
|
||||
|
||||
#
|
||||
# Parallel port support
|
||||
|
@ -372,52 +317,21 @@ CONFIG_MTD_NAND_IDS=y
|
|||
# Block devices
|
||||
#
|
||||
# CONFIG_BLK_DEV_COW_COMMON is not set
|
||||
CONFIG_BLK_DEV_LOOP=m
|
||||
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
|
||||
# CONFIG_BLK_DEV_LOOP is not set
|
||||
# CONFIG_BLK_DEV_NBD is not set
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_COUNT=2
|
||||
CONFIG_BLK_DEV_RAM_SIZE=16384
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
# CONFIG_BLK_DEV_RAM is not set
|
||||
CONFIG_BLK_DEV_RAM_COUNT=16
|
||||
# CONFIG_CDROM_PKTCDVD is not set
|
||||
|
||||
#
|
||||
# IO Schedulers
|
||||
#
|
||||
CONFIG_IOSCHED_NOOP=y
|
||||
CONFIG_IOSCHED_AS=y
|
||||
# CONFIG_IOSCHED_AS is not set
|
||||
CONFIG_IOSCHED_DEADLINE=y
|
||||
CONFIG_IOSCHED_CFQ=y
|
||||
# CONFIG_IOSCHED_CFQ is not set
|
||||
# CONFIG_ATA_OVER_ETH is not set
|
||||
|
||||
#
|
||||
# ATA/ATAPI/MFM/RLL support
|
||||
#
|
||||
CONFIG_IDE=y
|
||||
CONFIG_BLK_DEV_IDE=y
|
||||
|
||||
#
|
||||
# Please see Documentation/ide.txt for help/info on IDE drives
|
||||
#
|
||||
# CONFIG_BLK_DEV_IDE_SATA is not set
|
||||
# CONFIG_BLK_DEV_HD_IDE is not set
|
||||
CONFIG_BLK_DEV_IDEDISK=y
|
||||
# CONFIG_IDEDISK_MULTI_MODE is not set
|
||||
# CONFIG_BLK_DEV_IDECD is not set
|
||||
# CONFIG_BLK_DEV_IDETAPE is not set
|
||||
# CONFIG_BLK_DEV_IDEFLOPPY is not set
|
||||
# CONFIG_IDE_TASK_IOCTL is not set
|
||||
|
||||
#
|
||||
# IDE chipset support/bugfixes
|
||||
#
|
||||
# CONFIG_IDE_GENERIC is not set
|
||||
CONFIG_IDE_ARM=y
|
||||
CONFIG_BLK_DEV_IDE_MP1000=y
|
||||
# CONFIG_BLK_DEV_IDEDMA is not set
|
||||
# CONFIG_IDEDMA_AUTO is not set
|
||||
# CONFIG_BLK_DEV_HD is not set
|
||||
|
||||
#
|
||||
# SCSI device support
|
||||
#
|
||||
|
@ -427,14 +341,7 @@ CONFIG_BLK_DEV_IDE_MP1000=y
|
|||
#
|
||||
# Multi-device support (RAID and LVM)
|
||||
#
|
||||
CONFIG_MD=y
|
||||
# CONFIG_BLK_DEV_MD is not set
|
||||
CONFIG_BLK_DEV_DM=y
|
||||
# CONFIG_DM_CRYPT is not set
|
||||
# CONFIG_DM_SNAPSHOT is not set
|
||||
# CONFIG_DM_MIRROR is not set
|
||||
# CONFIG_DM_ZERO is not set
|
||||
# CONFIG_DM_MULTIPATH is not set
|
||||
# CONFIG_MD is not set
|
||||
|
||||
#
|
||||
# Fusion MPT device support
|
||||
|
@ -444,7 +351,6 @@ CONFIG_BLK_DEV_DM=y
|
|||
#
|
||||
# IEEE 1394 (FireWire) support
|
||||
#
|
||||
# CONFIG_IEEE1394 is not set
|
||||
|
||||
#
|
||||
# I2O device support
|
||||
|
@ -468,10 +374,9 @@ CONFIG_NETDEVICES=y
|
|||
# Ethernet (10 or 100Mbit)
|
||||
#
|
||||
CONFIG_NET_ETHERNET=y
|
||||
# CONFIG_MII is not set
|
||||
# CONFIG_SMC91X is not set
|
||||
CONFIG_MII=y
|
||||
CONFIG_SMC91X=y
|
||||
# CONFIG_DM9000 is not set
|
||||
CONFIG_CS89x0=y
|
||||
|
||||
#
|
||||
# Ethernet (1000 Mbit)
|
||||
|
@ -496,8 +401,6 @@ CONFIG_CS89x0=y
|
|||
# CONFIG_WAN is not set
|
||||
# CONFIG_PPP is not set
|
||||
# CONFIG_SLIP is not set
|
||||
# CONFIG_SHAPER is not set
|
||||
# CONFIG_NETCONSOLE is not set
|
||||
# CONFIG_NETPOLL is not set
|
||||
# CONFIG_NET_POLL_CONTROLLER is not set
|
||||
|
||||
|
@ -514,17 +417,28 @@ CONFIG_INPUT=y
|
|||
#
|
||||
# Userland interfaces
|
||||
#
|
||||
# CONFIG_INPUT_MOUSEDEV is not set
|
||||
CONFIG_INPUT_MOUSEDEV=y
|
||||
CONFIG_INPUT_MOUSEDEV_PSAUX=y
|
||||
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
|
||||
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
|
||||
# CONFIG_INPUT_JOYDEV is not set
|
||||
# CONFIG_INPUT_TSDEV is not set
|
||||
# CONFIG_INPUT_EVDEV is not set
|
||||
CONFIG_INPUT_EVBUG=y
|
||||
# CONFIG_INPUT_EVBUG is not set
|
||||
|
||||
#
|
||||
# Input Device Drivers
|
||||
#
|
||||
# CONFIG_INPUT_KEYBOARD is not set
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
CONFIG_INPUT_KEYBOARD=y
|
||||
CONFIG_KEYBOARD_ATKBD=y
|
||||
# CONFIG_KEYBOARD_SUNKBD is not set
|
||||
# CONFIG_KEYBOARD_LKKBD is not set
|
||||
# CONFIG_KEYBOARD_XTKBD is not set
|
||||
# CONFIG_KEYBOARD_NEWTON is not set
|
||||
CONFIG_INPUT_MOUSE=y
|
||||
CONFIG_MOUSE_PS2=y
|
||||
# CONFIG_MOUSE_SERIAL is not set
|
||||
# CONFIG_MOUSE_VSXXXAA is not set
|
||||
# CONFIG_INPUT_JOYSTICK is not set
|
||||
# CONFIG_INPUT_TOUCHSCREEN is not set
|
||||
# CONFIG_INPUT_MISC is not set
|
||||
|
@ -533,8 +447,9 @@ CONFIG_INPUT_EVBUG=y
|
|||
# Hardware I/O ports
|
||||
#
|
||||
CONFIG_SERIO=y
|
||||
CONFIG_SERIO_SERPORT=y
|
||||
# CONFIG_SERIO_LIBPS2 is not set
|
||||
# CONFIG_SERIO_SERPORT is not set
|
||||
CONFIG_SERIO_AMBAKMI=y
|
||||
CONFIG_SERIO_LIBPS2=y
|
||||
# CONFIG_SERIO_RAW is not set
|
||||
# CONFIG_GAMEPORT is not set
|
||||
|
||||
|
@ -549,21 +464,19 @@ CONFIG_HW_CONSOLE=y
|
|||
#
|
||||
# Serial drivers
|
||||
#
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=2
|
||||
# CONFIG_SERIAL_8250_EXTENDED is not set
|
||||
# CONFIG_SERIAL_8250 is not set
|
||||
|
||||
#
|
||||
# Non-8250 serial port support
|
||||
#
|
||||
CONFIG_SERIAL_CLPS711X=y
|
||||
CONFIG_SERIAL_CLPS711X_CONSOLE=y
|
||||
# CONFIG_SERIAL_AMBA_PL010 is not set
|
||||
CONFIG_SERIAL_AMBA_PL011=y
|
||||
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
|
||||
CONFIG_SERIAL_CORE=y
|
||||
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
CONFIG_LEGACY_PTYS=y
|
||||
CONFIG_LEGACY_PTY_COUNT=256
|
||||
CONFIG_LEGACY_PTY_COUNT=16
|
||||
|
||||
#
|
||||
# IPMI
|
||||
|
@ -574,8 +487,8 @@ CONFIG_LEGACY_PTY_COUNT=256
|
|||
# Watchdog Cards
|
||||
#
|
||||
# CONFIG_WATCHDOG is not set
|
||||
CONFIG_NVRAM=y
|
||||
CONFIG_RTC=y
|
||||
# CONFIG_NVRAM is not set
|
||||
# CONFIG_RTC is not set
|
||||
# CONFIG_DTLK is not set
|
||||
# CONFIG_R3964 is not set
|
||||
|
||||
|
@ -596,9 +509,8 @@ CONFIG_RTC=y
|
|||
#
|
||||
# Hardware Monitoring support
|
||||
#
|
||||
CONFIG_HWMON=y
|
||||
# CONFIG_HWMON is not set
|
||||
# CONFIG_HWMON_VID is not set
|
||||
# CONFIG_HWMON_DEBUG_CHIP is not set
|
||||
|
||||
#
|
||||
# Misc devices
|
||||
|
@ -621,18 +533,72 @@ CONFIG_HWMON=y
|
|||
#
|
||||
# Graphics support
|
||||
#
|
||||
# CONFIG_FB is not set
|
||||
CONFIG_FB=y
|
||||
CONFIG_FB_CFB_FILLRECT=y
|
||||
CONFIG_FB_CFB_COPYAREA=y
|
||||
CONFIG_FB_CFB_IMAGEBLIT=y
|
||||
CONFIG_FB_SOFT_CURSOR=y
|
||||
# CONFIG_FB_MACMODES is not set
|
||||
# CONFIG_FB_MODE_HELPERS is not set
|
||||
# CONFIG_FB_TILEBLITTING is not set
|
||||
CONFIG_FB_ARMCLCD=y
|
||||
# CONFIG_FB_S1D13XXX is not set
|
||||
# CONFIG_FB_VIRTUAL is not set
|
||||
|
||||
#
|
||||
# Console display driver support
|
||||
#
|
||||
# CONFIG_VGA_CONSOLE is not set
|
||||
CONFIG_DUMMY_CONSOLE=y
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
# CONFIG_FONTS is not set
|
||||
CONFIG_FONT_8x8=y
|
||||
CONFIG_FONT_8x16=y
|
||||
|
||||
#
|
||||
# Logo configuration
|
||||
#
|
||||
CONFIG_LOGO=y
|
||||
# CONFIG_LOGO_LINUX_MONO is not set
|
||||
# CONFIG_LOGO_LINUX_VGA16 is not set
|
||||
CONFIG_LOGO_LINUX_CLUT224=y
|
||||
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
|
||||
|
||||
#
|
||||
# Sound
|
||||
#
|
||||
# CONFIG_SOUND is not set
|
||||
CONFIG_SOUND=y
|
||||
|
||||
#
|
||||
# Advanced Linux Sound Architecture
|
||||
#
|
||||
CONFIG_SND=y
|
||||
CONFIG_SND_TIMER=y
|
||||
CONFIG_SND_PCM=y
|
||||
# CONFIG_SND_SEQUENCER is not set
|
||||
CONFIG_SND_OSSEMUL=y
|
||||
CONFIG_SND_MIXER_OSS=y
|
||||
CONFIG_SND_PCM_OSS=y
|
||||
# CONFIG_SND_VERBOSE_PRINTK is not set
|
||||
# CONFIG_SND_DEBUG is not set
|
||||
|
||||
#
|
||||
# Generic devices
|
||||
#
|
||||
# CONFIG_SND_DUMMY is not set
|
||||
# CONFIG_SND_MTPAV is not set
|
||||
# CONFIG_SND_SERIAL_U16550 is not set
|
||||
# CONFIG_SND_MPU401 is not set
|
||||
|
||||
#
|
||||
# ALSA ARM devices
|
||||
#
|
||||
# CONFIG_SND_ARMAACI is not set
|
||||
|
||||
#
|
||||
# Open Sound System
|
||||
#
|
||||
# CONFIG_SOUND_PRIME is not set
|
||||
|
||||
#
|
||||
# USB support
|
||||
|
@ -654,32 +620,17 @@ CONFIG_USB_ARCH_HAS_HCD=y
|
|||
#
|
||||
# File systems
|
||||
#
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT2_FS_XATTR=y
|
||||
# CONFIG_EXT2_FS_POSIX_ACL is not set
|
||||
# CONFIG_EXT2_FS_SECURITY is not set
|
||||
# CONFIG_EXT2_FS_XIP is not set
|
||||
CONFIG_EXT3_FS=y
|
||||
CONFIG_EXT3_FS_XATTR=y
|
||||
# CONFIG_EXT3_FS_POSIX_ACL is not set
|
||||
# CONFIG_EXT3_FS_SECURITY is not set
|
||||
CONFIG_JBD=y
|
||||
# CONFIG_JBD_DEBUG is not set
|
||||
CONFIG_FS_MBCACHE=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
# CONFIG_REISERFS_CHECK is not set
|
||||
# CONFIG_REISERFS_PROC_INFO is not set
|
||||
# CONFIG_REISERFS_FS_XATTR is not set
|
||||
# CONFIG_EXT2_FS is not set
|
||||
# CONFIG_EXT3_FS is not set
|
||||
# CONFIG_JBD is not set
|
||||
# CONFIG_REISERFS_FS is not set
|
||||
# CONFIG_JFS_FS is not set
|
||||
CONFIG_FS_POSIX_ACL=y
|
||||
# CONFIG_FS_POSIX_ACL is not set
|
||||
# CONFIG_XFS_FS is not set
|
||||
# CONFIG_MINIX_FS is not set
|
||||
# CONFIG_ROMFS_FS is not set
|
||||
CONFIG_INOTIFY=y
|
||||
CONFIG_QUOTA=y
|
||||
# CONFIG_QFMT_V1 is not set
|
||||
# CONFIG_QFMT_V2 is not set
|
||||
CONFIG_QUOTACTL=y
|
||||
# CONFIG_QUOTA is not set
|
||||
CONFIG_DNOTIFY=y
|
||||
# CONFIG_AUTOFS_FS is not set
|
||||
# CONFIG_AUTOFS4_FS is not set
|
||||
|
@ -694,8 +645,11 @@ CONFIG_DNOTIFY=y
|
|||
#
|
||||
# DOS/FAT/NT Filesystems
|
||||
#
|
||||
CONFIG_FAT_FS=y
|
||||
# CONFIG_MSDOS_FS is not set
|
||||
# CONFIG_VFAT_FS is not set
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_FAT_DEFAULT_CODEPAGE=437
|
||||
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
|
||||
# CONFIG_NTFS_FS is not set
|
||||
|
||||
#
|
||||
|
@ -704,7 +658,6 @@ CONFIG_DNOTIFY=y
|
|||
CONFIG_PROC_FS=y
|
||||
CONFIG_SYSFS=y
|
||||
CONFIG_TMPFS=y
|
||||
# CONFIG_HUGETLBFS is not set
|
||||
# CONFIG_HUGETLB_PAGE is not set
|
||||
CONFIG_RAMFS=y
|
||||
# CONFIG_RELAYFS_FS is not set
|
||||
|
@ -712,22 +665,10 @@ CONFIG_RAMFS=y
|
|||
#
|
||||
# Miscellaneous filesystems
|
||||
#
|
||||
# CONFIG_ADFS_FS is not set
|
||||
# CONFIG_AFFS_FS is not set
|
||||
# CONFIG_HFS_FS is not set
|
||||
# CONFIG_HFSPLUS_FS is not set
|
||||
# CONFIG_BEFS_FS is not set
|
||||
# CONFIG_BFS_FS is not set
|
||||
# CONFIG_EFS_FS is not set
|
||||
# CONFIG_JFFS_FS is not set
|
||||
CONFIG_JFFS2_FS=m
|
||||
CONFIG_JFFS2_FS_DEBUG=0
|
||||
CONFIG_JFFS2_FS_WRITEBUFFER=y
|
||||
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
|
||||
CONFIG_JFFS2_ZLIB=y
|
||||
CONFIG_JFFS2_RTIME=y
|
||||
# CONFIG_JFFS2_RUBIN is not set
|
||||
CONFIG_CRAMFS=m
|
||||
# CONFIG_JFFS2_FS is not set
|
||||
CONFIG_CRAMFS=y
|
||||
# CONFIG_VXFS_FS is not set
|
||||
# CONFIG_HPFS_FS is not set
|
||||
# CONFIG_QNX4FS_FS is not set
|
||||
|
@ -740,32 +681,16 @@ CONFIG_CRAMFS=m
|
|||
CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
# CONFIG_NFS_V3_ACL is not set
|
||||
CONFIG_NFS_V4=y
|
||||
# CONFIG_NFS_DIRECTIO is not set
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
# CONFIG_NFSD_V3_ACL is not set
|
||||
CONFIG_NFSD_V4=y
|
||||
CONFIG_NFSD_TCP=y
|
||||
# CONFIG_NFSD is not set
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_LOCKD=y
|
||||
CONFIG_LOCKD_V4=y
|
||||
CONFIG_EXPORTFS=y
|
||||
CONFIG_NFS_COMMON=y
|
||||
CONFIG_SUNRPC=y
|
||||
CONFIG_SUNRPC_GSS=y
|
||||
CONFIG_RPCSEC_GSS_KRB5=y
|
||||
# CONFIG_RPCSEC_GSS_SPKM3 is not set
|
||||
CONFIG_SMB_FS=m
|
||||
# CONFIG_SMB_NLS_DEFAULT is not set
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS is not set
|
||||
# CONFIG_CIFS_XATTR is not set
|
||||
# CONFIG_CIFS_EXPERIMENTAL is not set
|
||||
# CONFIG_SMB_FS is not set
|
||||
# CONFIG_CIFS is not set
|
||||
# CONFIG_NCP_FS is not set
|
||||
# CONFIG_CODA_FS is not set
|
||||
# CONFIG_AFS_FS is not set
|
||||
# CONFIG_9P_FS is not set
|
||||
|
||||
#
|
||||
# Partition Types
|
||||
|
@ -802,7 +727,7 @@ CONFIG_NLS_CODEPAGE_437=y
|
|||
# CONFIG_NLS_CODEPAGE_1250 is not set
|
||||
# CONFIG_NLS_CODEPAGE_1251 is not set
|
||||
# CONFIG_NLS_ASCII is not set
|
||||
# CONFIG_NLS_ISO8859_1 is not set
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
# CONFIG_NLS_ISO8859_2 is not set
|
||||
# CONFIG_NLS_ISO8859_3 is not set
|
||||
# CONFIG_NLS_ISO8859_4 is not set
|
||||
|
@ -817,35 +742,27 @@ CONFIG_NLS_CODEPAGE_437=y
|
|||
# CONFIG_NLS_KOI8_U is not set
|
||||
# CONFIG_NLS_UTF8 is not set
|
||||
|
||||
#
|
||||
# Profiling support
|
||||
#
|
||||
# CONFIG_PROFILING is not set
|
||||
|
||||
#
|
||||
# Kernel hacking
|
||||
#
|
||||
CONFIG_PRINTK_TIME=y
|
||||
# CONFIG_PRINTK_TIME is not set
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
# CONFIG_MAGIC_SYSRQ is not set
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
CONFIG_DETECT_SOFTLOCKUP=y
|
||||
# CONFIG_SCHEDSTATS is not set
|
||||
# CONFIG_DEBUG_SLAB is not set
|
||||
CONFIG_DEBUG_PREEMPT=y
|
||||
# CONFIG_DEBUG_SPINLOCK is not set
|
||||
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
|
||||
# CONFIG_DEBUG_KOBJECT is not set
|
||||
# CONFIG_DEBUG_BUGVERBOSE is not set
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_BUGVERBOSE=y
|
||||
# CONFIG_DEBUG_INFO is not set
|
||||
# CONFIG_DEBUG_FS is not set
|
||||
CONFIG_FRAME_POINTER=y
|
||||
CONFIG_DEBUG_USER=y
|
||||
CONFIG_DEBUG_WAITQ=y
|
||||
# CONFIG_DEBUG_WAITQ is not set
|
||||
CONFIG_DEBUG_ERRORS=y
|
||||
CONFIG_DEBUG_LL=y
|
||||
# CONFIG_DEBUG_ICEDCC is not set
|
||||
# CONFIG_DEBUG_CLPS711X_UART2 is not set
|
||||
# CONFIG_DEBUG_LL is not set
|
||||
|
||||
#
|
||||
# Security options
|
||||
|
@ -856,31 +773,7 @@ CONFIG_DEBUG_LL=y
|
|||
#
|
||||
# Cryptographic options
|
||||
#
|
||||
CONFIG_CRYPTO=y
|
||||
# CONFIG_CRYPTO_HMAC is not set
|
||||
# CONFIG_CRYPTO_NULL is not set
|
||||
# CONFIG_CRYPTO_MD4 is not set
|
||||
CONFIG_CRYPTO_MD5=y
|
||||
# CONFIG_CRYPTO_SHA1 is not set
|
||||
# CONFIG_CRYPTO_SHA256 is not set
|
||||
# CONFIG_CRYPTO_SHA512 is not set
|
||||
# CONFIG_CRYPTO_WP512 is not set
|
||||
# CONFIG_CRYPTO_TGR192 is not set
|
||||
CONFIG_CRYPTO_DES=y
|
||||
# CONFIG_CRYPTO_BLOWFISH is not set
|
||||
# CONFIG_CRYPTO_TWOFISH is not set
|
||||
# CONFIG_CRYPTO_SERPENT is not set
|
||||
# CONFIG_CRYPTO_AES is not set
|
||||
# CONFIG_CRYPTO_CAST5 is not set
|
||||
# CONFIG_CRYPTO_CAST6 is not set
|
||||
# CONFIG_CRYPTO_TEA is not set
|
||||
# CONFIG_CRYPTO_ARC4 is not set
|
||||
# CONFIG_CRYPTO_KHAZAD is not set
|
||||
# CONFIG_CRYPTO_ANUBIS is not set
|
||||
# CONFIG_CRYPTO_DEFLATE is not set
|
||||
# CONFIG_CRYPTO_MICHAEL_MIC is not set
|
||||
# CONFIG_CRYPTO_CRC32C is not set
|
||||
# CONFIG_CRYPTO_TEST is not set
|
||||
# CONFIG_CRYPTO is not set
|
||||
|
||||
#
|
||||
# Hardware crypto devices
|
||||
|
@ -893,5 +786,4 @@ CONFIG_CRYPTO_DES=y
|
|||
# CONFIG_CRC16 is not set
|
||||
CONFIG_CRC32=y
|
||||
# CONFIG_LIBCRC32C is not set
|
||||
CONFIG_ZLIB_INFLATE=m
|
||||
CONFIG_ZLIB_DEFLATE=m
|
||||
CONFIG_ZLIB_INFLATE=y
|
|
@ -785,7 +785,7 @@ __kuser_helper_end:
|
|||
* SP points to a minimal amount of processor-private memory, the address
|
||||
* of which is copied into r0 for the mode specific abort handler.
|
||||
*/
|
||||
.macro vector_stub, name, correction=0
|
||||
.macro vector_stub, name, mode, correction=0
|
||||
.align 5
|
||||
|
||||
vector_\name:
|
||||
|
@ -805,15 +805,14 @@ vector_\name:
|
|||
@ Prepare for SVC32 mode. IRQs remain disabled.
|
||||
@
|
||||
mrs r0, cpsr
|
||||
bic r0, r0, #MODE_MASK
|
||||
orr r0, r0, #SVC_MODE
|
||||
eor r0, r0, #(\mode ^ SVC_MODE)
|
||||
msr spsr_cxsf, r0
|
||||
|
||||
@
|
||||
@ the branch table must immediately follow this code
|
||||
@
|
||||
mov r0, sp
|
||||
and lr, lr, #0x0f
|
||||
mov r0, sp
|
||||
ldr lr, [pc, lr, lsl #2]
|
||||
movs pc, lr @ branch to handler in SVC mode
|
||||
.endm
|
||||
|
@ -823,7 +822,7 @@ __stubs_start:
|
|||
/*
|
||||
* Interrupt dispatcher
|
||||
*/
|
||||
vector_stub irq, 4
|
||||
vector_stub irq, IRQ_MODE, 4
|
||||
|
||||
.long __irq_usr @ 0 (USR_26 / USR_32)
|
||||
.long __irq_invalid @ 1 (FIQ_26 / FIQ_32)
|
||||
|
@ -846,7 +845,7 @@ __stubs_start:
|
|||
* Data abort dispatcher
|
||||
* Enter in ABT mode, spsr = USR CPSR, lr = USR PC
|
||||
*/
|
||||
vector_stub dabt, 8
|
||||
vector_stub dabt, ABT_MODE, 8
|
||||
|
||||
.long __dabt_usr @ 0 (USR_26 / USR_32)
|
||||
.long __dabt_invalid @ 1 (FIQ_26 / FIQ_32)
|
||||
|
@ -869,7 +868,7 @@ __stubs_start:
|
|||
* Prefetch abort dispatcher
|
||||
* Enter in ABT mode, spsr = USR CPSR, lr = USR PC
|
||||
*/
|
||||
vector_stub pabt, 4
|
||||
vector_stub pabt, ABT_MODE, 4
|
||||
|
||||
.long __pabt_usr @ 0 (USR_26 / USR_32)
|
||||
.long __pabt_invalid @ 1 (FIQ_26 / FIQ_32)
|
||||
|
@ -892,7 +891,7 @@ __stubs_start:
|
|||
* Undef instr entry dispatcher
|
||||
* Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
|
||||
*/
|
||||
vector_stub und
|
||||
vector_stub und, UND_MODE
|
||||
|
||||
.long __und_usr @ 0 (USR_26 / USR_32)
|
||||
.long __und_invalid @ 1 (FIQ_26 / FIQ_32)
|
||||
|
|
|
@ -338,7 +338,8 @@ void cpu_init(void)
|
|||
BUG();
|
||||
}
|
||||
|
||||
dump_cpu_info(cpu);
|
||||
if (system_state == SYSTEM_BOOTING)
|
||||
dump_cpu_info(cpu);
|
||||
|
||||
/*
|
||||
* setup stacks for re-entrant exception handlers
|
||||
|
@ -838,7 +839,12 @@ static int c_show(struct seq_file *m, void *v)
|
|||
|
||||
#if defined(CONFIG_SMP)
|
||||
for_each_online_cpu(i) {
|
||||
seq_printf(m, "Processor\t: %d\n", i);
|
||||
/*
|
||||
* glibc reads /proc/cpuinfo to determine the number of
|
||||
* online processors, looking for lines beginning with
|
||||
* "processor". Give glibc what it expects.
|
||||
*/
|
||||
seq_printf(m, "processor\t: %d\n", i);
|
||||
seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
|
||||
per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
|
||||
(per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include <linux/config.h>
|
||||
|
||||
#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_MPCORE)
|
||||
#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_32v6K)
|
||||
.macro bitop, instr
|
||||
mov r2, #1
|
||||
and r3, r0, #7 @ Get bit offset
|
||||
|
|
|
@ -43,8 +43,6 @@ ENTRY(__arch_copy_to_user)
|
|||
stmfd sp!, {r2, r4 - r7, lr}
|
||||
cmp r2, #4
|
||||
blt .c2u_not_enough
|
||||
PLD( pld [r1, #0] )
|
||||
PLD( pld [r0, #0] )
|
||||
ands ip, r0, #3
|
||||
bne .c2u_dest_not_aligned
|
||||
.c2u_dest_aligned:
|
||||
|
@ -73,25 +71,13 @@ USER( strt r3, [r0], #4) @ May fault
|
|||
sub r2, r2, ip
|
||||
subs ip, ip, #32
|
||||
blt .c2u_0rem8lp
|
||||
PLD( pld [r1, #28] )
|
||||
PLD( pld [r0, #28] )
|
||||
PLD( subs ip, ip, #64 )
|
||||
PLD( blt .c2u_0cpynopld )
|
||||
PLD( pld [r1, #60] )
|
||||
PLD( pld [r0, #60] )
|
||||
|
||||
.c2u_0cpy8lp:
|
||||
PLD( pld [r1, #92] )
|
||||
PLD( pld [r0, #92] )
|
||||
.c2u_0cpynopld: ldmia r1!, {r3 - r6}
|
||||
.c2u_0cpy8lp: ldmia r1!, {r3 - r6}
|
||||
stmia r0!, {r3 - r6} @ Shouldnt fault
|
||||
ldmia r1!, {r3 - r6}
|
||||
subs ip, ip, #32
|
||||
stmia r0!, {r3 - r6} @ Shouldnt fault
|
||||
bpl .c2u_0cpy8lp
|
||||
PLD( cmn ip, #64 )
|
||||
PLD( bge .c2u_0cpynopld )
|
||||
PLD( add ip, ip, #64 )
|
||||
|
||||
.c2u_0rem8lp: cmn ip, #16
|
||||
ldmgeia r1!, {r3 - r6}
|
||||
|
@ -143,17 +129,8 @@ USER( strt r3, [r0], #4) @ May fault
|
|||
sub r2, r2, ip
|
||||
subs ip, ip, #16
|
||||
blt .c2u_1rem8lp
|
||||
PLD( pld [r1, #12] )
|
||||
PLD( pld [r0, #12] )
|
||||
PLD( subs ip, ip, #32 )
|
||||
PLD( blt .c2u_1cpynopld )
|
||||
PLD( pld [r1, #28] )
|
||||
PLD( pld [r0, #28] )
|
||||
|
||||
.c2u_1cpy8lp:
|
||||
PLD( pld [r1, #44] )
|
||||
PLD( pld [r0, #44] )
|
||||
.c2u_1cpynopld: mov r3, r7, pull #8
|
||||
.c2u_1cpy8lp: mov r3, r7, pull #8
|
||||
ldmia r1!, {r4 - r7}
|
||||
subs ip, ip, #16
|
||||
orr r3, r3, r4, push #24
|
||||
|
@ -165,9 +142,6 @@ USER( strt r3, [r0], #4) @ May fault
|
|||
orr r6, r6, r7, push #24
|
||||
stmia r0!, {r3 - r6} @ Shouldnt fault
|
||||
bpl .c2u_1cpy8lp
|
||||
PLD( cmn ip, #32 )
|
||||
PLD( bge .c2u_1cpynopld )
|
||||
PLD( add ip, ip, #32 )
|
||||
|
||||
.c2u_1rem8lp: tst ip, #8
|
||||
movne r3, r7, pull #8
|
||||
|
@ -210,17 +184,8 @@ USER( strt r3, [r0], #4) @ May fault
|
|||
sub r2, r2, ip
|
||||
subs ip, ip, #16
|
||||
blt .c2u_2rem8lp
|
||||
PLD( pld [r1, #12] )
|
||||
PLD( pld [r0, #12] )
|
||||
PLD( subs ip, ip, #32 )
|
||||
PLD( blt .c2u_2cpynopld )
|
||||
PLD( pld [r1, #28] )
|
||||
PLD( pld [r0, #28] )
|
||||
|
||||
.c2u_2cpy8lp:
|
||||
PLD( pld [r1, #44] )
|
||||
PLD( pld [r0, #44] )
|
||||
.c2u_2cpynopld: mov r3, r7, pull #16
|
||||
.c2u_2cpy8lp: mov r3, r7, pull #16
|
||||
ldmia r1!, {r4 - r7}
|
||||
subs ip, ip, #16
|
||||
orr r3, r3, r4, push #16
|
||||
|
@ -232,9 +197,6 @@ USER( strt r3, [r0], #4) @ May fault
|
|||
orr r6, r6, r7, push #16
|
||||
stmia r0!, {r3 - r6} @ Shouldnt fault
|
||||
bpl .c2u_2cpy8lp
|
||||
PLD( cmn ip, #32 )
|
||||
PLD( bge .c2u_2cpynopld )
|
||||
PLD( add ip, ip, #32 )
|
||||
|
||||
.c2u_2rem8lp: tst ip, #8
|
||||
movne r3, r7, pull #16
|
||||
|
@ -277,17 +239,8 @@ USER( strt r3, [r0], #4) @ May fault
|
|||
sub r2, r2, ip
|
||||
subs ip, ip, #16
|
||||
blt .c2u_3rem8lp
|
||||
PLD( pld [r1, #12] )
|
||||
PLD( pld [r0, #12] )
|
||||
PLD( subs ip, ip, #32 )
|
||||
PLD( blt .c2u_3cpynopld )
|
||||
PLD( pld [r1, #28] )
|
||||
PLD( pld [r0, #28] )
|
||||
|
||||
.c2u_3cpy8lp:
|
||||
PLD( pld [r1, #44] )
|
||||
PLD( pld [r0, #44] )
|
||||
.c2u_3cpynopld: mov r3, r7, pull #24
|
||||
.c2u_3cpy8lp: mov r3, r7, pull #24
|
||||
ldmia r1!, {r4 - r7}
|
||||
subs ip, ip, #16
|
||||
orr r3, r3, r4, push #8
|
||||
|
@ -299,9 +252,6 @@ USER( strt r3, [r0], #4) @ May fault
|
|||
orr r6, r6, r7, push #8
|
||||
stmia r0!, {r3 - r6} @ Shouldnt fault
|
||||
bpl .c2u_3cpy8lp
|
||||
PLD( cmn ip, #32 )
|
||||
PLD( bge .c2u_3cpynopld )
|
||||
PLD( add ip, ip, #32 )
|
||||
|
||||
.c2u_3rem8lp: tst ip, #8
|
||||
movne r3, r7, pull #24
|
||||
|
@ -356,8 +306,6 @@ ENTRY(__arch_copy_from_user)
|
|||
stmfd sp!, {r0, r2, r4 - r7, lr}
|
||||
cmp r2, #4
|
||||
blt .cfu_not_enough
|
||||
PLD( pld [r1, #0] )
|
||||
PLD( pld [r0, #0] )
|
||||
ands ip, r0, #3
|
||||
bne .cfu_dest_not_aligned
|
||||
.cfu_dest_aligned:
|
||||
|
@ -385,25 +333,13 @@ USER( ldrt r3, [r1], #4)
|
|||
sub r2, r2, ip
|
||||
subs ip, ip, #32
|
||||
blt .cfu_0rem8lp
|
||||
PLD( pld [r1, #28] )
|
||||
PLD( pld [r0, #28] )
|
||||
PLD( subs ip, ip, #64 )
|
||||
PLD( blt .cfu_0cpynopld )
|
||||
PLD( pld [r1, #60] )
|
||||
PLD( pld [r0, #60] )
|
||||
|
||||
.cfu_0cpy8lp:
|
||||
PLD( pld [r1, #92] )
|
||||
PLD( pld [r0, #92] )
|
||||
.cfu_0cpynopld: ldmia r1!, {r3 - r6} @ Shouldnt fault
|
||||
.cfu_0cpy8lp: ldmia r1!, {r3 - r6} @ Shouldnt fault
|
||||
stmia r0!, {r3 - r6}
|
||||
ldmia r1!, {r3 - r6} @ Shouldnt fault
|
||||
subs ip, ip, #32
|
||||
stmia r0!, {r3 - r6}
|
||||
bpl .cfu_0cpy8lp
|
||||
PLD( cmn ip, #64 )
|
||||
PLD( bge .cfu_0cpynopld )
|
||||
PLD( add ip, ip, #64 )
|
||||
|
||||
.cfu_0rem8lp: cmn ip, #16
|
||||
ldmgeia r1!, {r3 - r6} @ Shouldnt fault
|
||||
|
@ -456,17 +392,8 @@ USER( ldrt r7, [r1], #4) @ May fault
|
|||
sub r2, r2, ip
|
||||
subs ip, ip, #16
|
||||
blt .cfu_1rem8lp
|
||||
PLD( pld [r1, #12] )
|
||||
PLD( pld [r0, #12] )
|
||||
PLD( subs ip, ip, #32 )
|
||||
PLD( blt .cfu_1cpynopld )
|
||||
PLD( pld [r1, #28] )
|
||||
PLD( pld [r0, #28] )
|
||||
|
||||
.cfu_1cpy8lp:
|
||||
PLD( pld [r1, #44] )
|
||||
PLD( pld [r0, #44] )
|
||||
.cfu_1cpynopld: mov r3, r7, pull #8
|
||||
.cfu_1cpy8lp: mov r3, r7, pull #8
|
||||
ldmia r1!, {r4 - r7} @ Shouldnt fault
|
||||
subs ip, ip, #16
|
||||
orr r3, r3, r4, push #24
|
||||
|
@ -478,9 +405,6 @@ USER( ldrt r7, [r1], #4) @ May fault
|
|||
orr r6, r6, r7, push #24
|
||||
stmia r0!, {r3 - r6}
|
||||
bpl .cfu_1cpy8lp
|
||||
PLD( cmn ip, #32 )
|
||||
PLD( bge .cfu_1cpynopld )
|
||||
PLD( add ip, ip, #32 )
|
||||
|
||||
.cfu_1rem8lp: tst ip, #8
|
||||
movne r3, r7, pull #8
|
||||
|
@ -523,17 +447,8 @@ USER( ldrt r7, [r1], #4) @ May fault
|
|||
sub r2, r2, ip
|
||||
subs ip, ip, #16
|
||||
blt .cfu_2rem8lp
|
||||
PLD( pld [r1, #12] )
|
||||
PLD( pld [r0, #12] )
|
||||
PLD( subs ip, ip, #32 )
|
||||
PLD( blt .cfu_2cpynopld )
|
||||
PLD( pld [r1, #28] )
|
||||
PLD( pld [r0, #28] )
|
||||
|
||||
.cfu_2cpy8lp:
|
||||
PLD( pld [r1, #44] )
|
||||
PLD( pld [r0, #44] )
|
||||
.cfu_2cpynopld: mov r3, r7, pull #16
|
||||
.cfu_2cpy8lp: mov r3, r7, pull #16
|
||||
ldmia r1!, {r4 - r7} @ Shouldnt fault
|
||||
subs ip, ip, #16
|
||||
orr r3, r3, r4, push #16
|
||||
|
@ -545,9 +460,6 @@ USER( ldrt r7, [r1], #4) @ May fault
|
|||
orr r6, r6, r7, push #16
|
||||
stmia r0!, {r3 - r6}
|
||||
bpl .cfu_2cpy8lp
|
||||
PLD( cmn ip, #32 )
|
||||
PLD( bge .cfu_2cpynopld )
|
||||
PLD( add ip, ip, #32 )
|
||||
|
||||
.cfu_2rem8lp: tst ip, #8
|
||||
movne r3, r7, pull #16
|
||||
|
@ -590,17 +502,8 @@ USER( ldrt r7, [r1], #4) @ May fault
|
|||
sub r2, r2, ip
|
||||
subs ip, ip, #16
|
||||
blt .cfu_3rem8lp
|
||||
PLD( pld [r1, #12] )
|
||||
PLD( pld [r0, #12] )
|
||||
PLD( subs ip, ip, #32 )
|
||||
PLD( blt .cfu_3cpynopld )
|
||||
PLD( pld [r1, #28] )
|
||||
PLD( pld [r0, #28] )
|
||||
|
||||
.cfu_3cpy8lp:
|
||||
PLD( pld [r1, #44] )
|
||||
PLD( pld [r0, #44] )
|
||||
.cfu_3cpynopld: mov r3, r7, pull #24
|
||||
.cfu_3cpy8lp: mov r3, r7, pull #24
|
||||
ldmia r1!, {r4 - r7} @ Shouldnt fault
|
||||
orr r3, r3, r4, push #8
|
||||
mov r4, r4, pull #24
|
||||
|
@ -612,9 +515,6 @@ USER( ldrt r7, [r1], #4) @ May fault
|
|||
stmia r0!, {r3 - r6}
|
||||
subs ip, ip, #16
|
||||
bpl .cfu_3cpy8lp
|
||||
PLD( cmn ip, #32 )
|
||||
PLD( bge .cfu_3cpynopld )
|
||||
PLD( add ip, ip, #32 )
|
||||
|
||||
.cfu_3rem8lp: tst ip, #8
|
||||
movne r3, r7, pull #24
|
||||
|
|
|
@ -69,17 +69,6 @@ config EP72XX_ROM_BOOT
|
|||
|
||||
You almost surely want to say N here.
|
||||
|
||||
config MACH_MP1000
|
||||
bool "MACH_MP1000"
|
||||
help
|
||||
Say Y if you intend to run the kernel on the Comdial MP1000 platform.
|
||||
|
||||
config MP1000_90MHZ
|
||||
bool "MP1000_90MHZ"
|
||||
depends on MACH_MP1000
|
||||
help
|
||||
Say Y if you have the MP1000 configured to be set at 90MHZ rather than 74MHZ
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
|
|
@ -15,7 +15,6 @@ obj-$(CONFIG_ARCH_CDB89712) += cdb89712.o
|
|||
obj-$(CONFIG_ARCH_CLEP7312) += clep7312.o
|
||||
obj-$(CONFIG_ARCH_EDB7211) += edb7211-arch.o edb7211-mm.o
|
||||
obj-$(CONFIG_ARCH_FORTUNET) += fortunet.o
|
||||
obj-$(CONFIG_MACH_MP1000) += mp1000-mach.o mp1000-mm.o mp1000-seprom.o
|
||||
obj-$(CONFIG_ARCH_P720T) += p720t.o
|
||||
leds-$(CONFIG_ARCH_P720T) += p720t-leds.o
|
||||
obj-$(CONFIG_LEDS) += $(leds-y)
|
||||
|
|
|
@ -55,22 +55,22 @@ static struct map_desc edb7211_io_desc[] __initdata = {
|
|||
.virtual = EP7211_VIRT_EXTKBD,
|
||||
.pfn = __phys_to_pfn(EP7211_PHYS_EXTKBD),
|
||||
.length = SZ_1M,
|
||||
.type - MT_DEVICE
|
||||
.type = MT_DEVICE,
|
||||
}, { /* and CS8900A Ethernet chip */
|
||||
.virtual = EP7211_VIRT_CS8900A,
|
||||
.pfn = __phys_to_pfn(EP7211_PHYS_CS8900A),
|
||||
.length = SZ_1M,
|
||||
.type = MT_DEVICE
|
||||
.type = MT_DEVICE,
|
||||
}, { /* flash banks */
|
||||
.virtual = EP7211_VIRT_FLASH1,
|
||||
.pfn = __phys_to_pfn(EP7211_PHYS_FLASH1),
|
||||
.length = SZ_8M,
|
||||
.type = MT_DEVICE
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = EP7211_VIRT_FLASH2,
|
||||
.pfn = __phys_to_pfn(EP7211_PHYS_FLASH2),
|
||||
.length = SZ_8M,
|
||||
.type = MT_DEVICE
|
||||
.type = MT_DEVICE,
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* linux/arch/arm/mach-mp1000/mp1000.c
|
||||
*
|
||||
* Copyright (C) 2005 Comdial 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
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/arch/mp1000-seprom.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
extern void mp1000_map_io(void);
|
||||
|
||||
static void __init mp1000_init(void)
|
||||
{
|
||||
seprom_init();
|
||||
}
|
||||
|
||||
MACHINE_START(MP1000, "Comdial MP1000")
|
||||
/* Maintainer: Jon Ringle */
|
||||
.phys_ram = 0xc0000000,
|
||||
.phys_io = 0x80000000,
|
||||
.io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
|
||||
.boot_params = 0xc0015100,
|
||||
.map_io = mp1000_map_io,
|
||||
.init_irq = clps711x_init_irq,
|
||||
.init_machine = mp1000_init,
|
||||
.timer = &clps711x_timer,
|
||||
MACHINE_END
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* linux/arch/arm/mach-mp1000/mm.c
|
||||
*
|
||||
* Extra MM routines for the MP1000
|
||||
*
|
||||
* Copyright (C) 2005 Comdial 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
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/sizes.h>
|
||||
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
extern void clps711x_map_io(void);
|
||||
|
||||
static struct map_desc mp1000_io_desc[] __initdata = {
|
||||
{ MP1000_EIO_BASE, MP1000_EIO_START, MP1000_EIO_SIZE, MT_DEVICE },
|
||||
{ MP1000_FIO_BASE, MP1000_FIO_START, MP1000_FIO_SIZE, MT_DEVICE },
|
||||
{ MP1000_LIO_BASE, MP1000_LIO_START, MP1000_LIO_SIZE, MT_DEVICE },
|
||||
{ MP1000_NIO_BASE, MP1000_NIO_START, MP1000_NIO_SIZE, MT_DEVICE },
|
||||
{ MP1000_IDE_BASE, MP1000_IDE_START, MP1000_IDE_SIZE, MT_DEVICE },
|
||||
{ MP1000_DSP_BASE, MP1000_DSP_START, MP1000_DSP_SIZE, MT_DEVICE }
|
||||
};
|
||||
|
||||
void __init mp1000_map_io(void)
|
||||
{
|
||||
clps711x_map_io();
|
||||
iotable_init(mp1000_io_desc, ARRAY_SIZE(mp1000_io_desc));
|
||||
}
|
|
@ -1,195 +0,0 @@
|
|||
/*`
|
||||
* mp1000-seprom.c
|
||||
*
|
||||
* This file contains the Serial EEPROM code for the MP1000 board
|
||||
*
|
||||
* Copyright (C) 2005 Comdial 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
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/hardware/clps7111.h>
|
||||
#include <asm/arch/mp1000-seprom.h>
|
||||
|
||||
/* If SepromInit() can initialize and checksum the seprom successfully, */
|
||||
/* then it will point seprom_data_ptr at the shadow copy. */
|
||||
|
||||
static eeprom_struct seprom_data; /* shadow copy of seprom content */
|
||||
|
||||
eeprom_struct *seprom_data_ptr = 0; /* 0 => not initialized */
|
||||
|
||||
/*
|
||||
* Port D Bit 5 is Chip Select for EEPROM
|
||||
* Port E Bit 0 is Input, Data out from EEPROM
|
||||
* Port E Bit 1 is Output, Data in to EEPROM
|
||||
* Port E Bit 2 is Output, CLK to EEPROM
|
||||
*/
|
||||
|
||||
static char *port_d_ptr = (char *)(CLPS7111_VIRT_BASE + PDDR);
|
||||
static char *port_e_ptr = (char *)(CLPS7111_VIRT_BASE + PEDR);
|
||||
|
||||
#define NO_OF_SHORTS 64 // Device is 64 x 16 bits
|
||||
#define ENABLE_RW 0
|
||||
#define DISABLE_RW 1
|
||||
|
||||
static inline void toggle_seprom_clock(void)
|
||||
{
|
||||
*port_e_ptr |= HwPortESepromCLK;
|
||||
*port_e_ptr &= ~(HwPortESepromCLK);
|
||||
}
|
||||
|
||||
static inline void select_eeprom(void)
|
||||
{
|
||||
*port_d_ptr |= HwPortDEECS;
|
||||
*port_e_ptr &= ~(HwPortESepromCLK);
|
||||
}
|
||||
|
||||
static inline void deselect_eeprom(void)
|
||||
{
|
||||
*port_d_ptr &= ~(HwPortDEECS);
|
||||
*port_e_ptr &= ~(HwPortESepromDIn);
|
||||
}
|
||||
|
||||
/*
|
||||
* GetSepromDataPtr - returns pointer to shadow (RAM) copy of seprom
|
||||
* and returns 0 if seprom is not initialized or
|
||||
* has a checksum error.
|
||||
*/
|
||||
|
||||
eeprom_struct* get_seprom_ptr(void)
|
||||
{
|
||||
return seprom_data_ptr;
|
||||
}
|
||||
|
||||
unsigned char* get_eeprom_mac_address(void)
|
||||
{
|
||||
return seprom_data_ptr->variant.eprom_struct.mac_Address;
|
||||
}
|
||||
|
||||
/*
|
||||
* ReadSProm, Physically reads data from the Serial PROM
|
||||
*/
|
||||
static void read_sprom(short address, int length, eeprom_struct *buffer)
|
||||
{
|
||||
short data = COMMAND_READ | (address & 0x3F);
|
||||
short bit;
|
||||
int i;
|
||||
|
||||
select_eeprom();
|
||||
|
||||
// Clock in 9 bits of the command
|
||||
for (i = 0, bit = 0x100; i < 9; i++, bit >>= 1) {
|
||||
if (data & bit)
|
||||
*port_e_ptr |= HwPortESepromDIn;
|
||||
else
|
||||
*port_e_ptr &= ~(HwPortESepromDIn);
|
||||
|
||||
toggle_seprom_clock();
|
||||
}
|
||||
|
||||
//
|
||||
// Now read one or more shorts of data from the Seprom
|
||||
//
|
||||
while (length-- > 0) {
|
||||
data = 0;
|
||||
|
||||
// Read 16 bits at a time
|
||||
for (i = 0; i < 16; i++) {
|
||||
data <<= 1;
|
||||
toggle_seprom_clock();
|
||||
data |= *port_e_ptr & HwPortESepromDOut;
|
||||
|
||||
}
|
||||
|
||||
buffer->variant.eprom_short_data[address++] = data;
|
||||
}
|
||||
|
||||
deselect_eeprom();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ReadSerialPROM
|
||||
*
|
||||
* Input: Pointer to array of 64 x 16 Bits
|
||||
*
|
||||
* Output: if no problem reading data is filled in
|
||||
*/
|
||||
static void read_serial_prom(eeprom_struct *data)
|
||||
{
|
||||
read_sprom(0, 64, data);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Compute Serial EEPROM checksum
|
||||
//
|
||||
// Input: Pointer to struct with Eprom data
|
||||
//
|
||||
// Output: The computed Eprom checksum
|
||||
//
|
||||
static short compute_seprom_checksum(eeprom_struct *data)
|
||||
{
|
||||
short checksum = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 126; i++) {
|
||||
checksum += (short)data->variant.eprom_byte_data[i];
|
||||
}
|
||||
|
||||
return((short)(0x5555 - (checksum & 0xFFFF)));
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure the data port bits for the SEPROM are correctly initialised
|
||||
//
|
||||
|
||||
void __init seprom_init(void)
|
||||
{
|
||||
short checksum;
|
||||
|
||||
// Init Port D
|
||||
*(char *)(CLPS7111_VIRT_BASE + PDDDR) = 0x0;
|
||||
*(char *)(CLPS7111_VIRT_BASE + PDDR) = 0x15;
|
||||
|
||||
// Init Port E
|
||||
*(int *)(CLPS7111_VIRT_BASE + PEDDR) = 0x06;
|
||||
*(int *)(CLPS7111_VIRT_BASE + PEDR) = 0x04;
|
||||
|
||||
//
|
||||
// Make sure that EEPROM struct size never exceeds 128 bytes
|
||||
//
|
||||
if (sizeof(eeprom_struct) > 128) {
|
||||
panic("Serial PROM struct size > 128, aborting read\n");
|
||||
}
|
||||
|
||||
read_serial_prom(&seprom_data);
|
||||
|
||||
checksum = compute_seprom_checksum(&seprom_data);
|
||||
|
||||
if (checksum != seprom_data.variant.eprom_short_data[63]) {
|
||||
panic("Serial EEPROM checksum failed\n");
|
||||
}
|
||||
|
||||
seprom_data_ptr = &seprom_data;
|
||||
}
|
||||
|
|
@ -402,6 +402,40 @@ static void ixp2000_pci_irq_unmask(unsigned int irq)
|
|||
ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 27)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Error interrupts. These are used extensively by the microengine drivers
|
||||
*/
|
||||
static void ixp2000_err_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
|
||||
{
|
||||
int i;
|
||||
unsigned long status = *IXP2000_IRQ_ERR_STATUS;
|
||||
|
||||
for(i = 31; i >= 0; i--) {
|
||||
if(status & (1 << i)) {
|
||||
desc = irq_desc + IRQ_IXP2000_DRAM0_MIN_ERR + i;
|
||||
desc->handle(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ixp2000_err_irq_mask(unsigned int irq)
|
||||
{
|
||||
ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_CLR,
|
||||
(1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)));
|
||||
}
|
||||
|
||||
static void ixp2000_err_irq_unmask(unsigned int irq)
|
||||
{
|
||||
ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_SET,
|
||||
(1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)));
|
||||
}
|
||||
|
||||
static struct irqchip ixp2000_err_irq_chip = {
|
||||
.ack = ixp2000_err_irq_mask,
|
||||
.mask = ixp2000_err_irq_mask,
|
||||
.unmask = ixp2000_err_irq_unmask
|
||||
};
|
||||
|
||||
static struct irqchip ixp2000_pci_irq_chip = {
|
||||
.ack = ixp2000_pci_irq_mask,
|
||||
.mask = ixp2000_pci_irq_mask,
|
||||
|
@ -459,6 +493,18 @@ void __init ixp2000_init_irq(void)
|
|||
} else set_irq_flags(irq, 0);
|
||||
}
|
||||
|
||||
for (irq = IRQ_IXP2000_DRAM0_MIN_ERR; irq <= IRQ_IXP2000_SP_INT; irq++) {
|
||||
if((1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)) &
|
||||
IXP2000_VALID_ERR_IRQ_MASK) {
|
||||
set_irq_chip(irq, &ixp2000_err_irq_chip);
|
||||
set_irq_handler(irq, do_level_IRQ);
|
||||
set_irq_flags(irq, IRQF_VALID);
|
||||
}
|
||||
else
|
||||
set_irq_flags(irq, 0);
|
||||
}
|
||||
set_irq_chained_handler(IRQ_IXP2000_ERRSUM, ixp2000_err_irq_handler);
|
||||
|
||||
/*
|
||||
* GPIO IRQs are invalid until someone sets the interrupt mode
|
||||
* by calling set_irq_type().
|
||||
|
|
|
@ -69,19 +69,19 @@ static struct sys_timer enp2611_timer = {
|
|||
static struct map_desc enp2611_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = ENP2611_CALEB_VIRT_BASE,
|
||||
.physical = ENP2611_CALEB_PHYS_BASE,
|
||||
.pfn = __phys_to_pfn(ENP2611_CALEB_PHYS_BASE),
|
||||
.length = ENP2611_CALEB_SIZE,
|
||||
.type = MT_IXP2000_DEVICE
|
||||
.type = MT_IXP2000_DEVICE,
|
||||
}, {
|
||||
.virtual = ENP2611_PM3386_0_VIRT_BASE,
|
||||
.physical = ENP2611_PM3386_0_PHYS_BASE,
|
||||
.pfn = __phys_to_pfn(ENP2611_PM3386_0_PHYS_BASE),
|
||||
.length = ENP2611_PM3386_0_SIZE,
|
||||
.type = MT_IXP2000_DEVICE
|
||||
.type = MT_IXP2000_DEVICE,
|
||||
}, {
|
||||
.virtual = ENP2611_PM3386_1_VIRT_BASE,
|
||||
.physical = ENP2611_PM3386_1_PHYS_BASE,
|
||||
.pfn = __phys_to_pfn(ENP2611_PM3386_1_PHYS_BASE),
|
||||
.length = ENP2611_PM3386_1_SIZE,
|
||||
.type = MT_IXP2000_DEVICE
|
||||
.type = MT_IXP2000_DEVICE,
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -91,8 +91,8 @@ EXPORT_SYMBOL(ixp2000_uengine_csr_write);
|
|||
|
||||
void ixp2000_uengine_reset(u32 uengine_mask)
|
||||
{
|
||||
ixp2000_reg_write(IXP2000_RESET1, uengine_mask & ixp2000_uengine_mask);
|
||||
ixp2000_reg_write(IXP2000_RESET1, 0);
|
||||
ixp2000_reg_wrb(IXP2000_RESET1, uengine_mask & ixp2000_uengine_mask);
|
||||
ixp2000_reg_wrb(IXP2000_RESET1, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(ixp2000_uengine_reset);
|
||||
|
||||
|
@ -452,21 +452,20 @@ static int __init ixp2000_uengine_init(void)
|
|||
/*
|
||||
* Reset microengines.
|
||||
*/
|
||||
ixp2000_reg_write(IXP2000_RESET1, ixp2000_uengine_mask);
|
||||
ixp2000_reg_write(IXP2000_RESET1, 0);
|
||||
ixp2000_uengine_reset(ixp2000_uengine_mask);
|
||||
|
||||
/*
|
||||
* Synchronise timestamp counters across all microengines.
|
||||
*/
|
||||
value = ixp2000_reg_read(IXP2000_MISC_CONTROL);
|
||||
ixp2000_reg_write(IXP2000_MISC_CONTROL, value & ~0x80);
|
||||
ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value & ~0x80);
|
||||
for (uengine = 0; uengine < 32; uengine++) {
|
||||
if (ixp2000_uengine_mask & (1 << uengine)) {
|
||||
ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0);
|
||||
ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0);
|
||||
}
|
||||
}
|
||||
ixp2000_reg_write(IXP2000_MISC_CONTROL, value | 0x80);
|
||||
ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value | 0x80);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -427,7 +427,7 @@ void __init ixp4xx_pci_preinit(void)
|
|||
#ifdef __ARMEB__
|
||||
*PCI_CSR = PCI_CSR_IC | PCI_CSR_ABE | PCI_CSR_PDS | PCI_CSR_ADS;
|
||||
#else
|
||||
*PCI_CSR = PCI_CSR_IC;
|
||||
*PCI_CSR = PCI_CSR_IC | PCI_CSR_ABE;
|
||||
#endif
|
||||
|
||||
pr_debug("DONE\n");
|
||||
|
|
|
@ -27,7 +27,8 @@ config PXA_SHARPSL
|
|||
Say Y here if you intend to run this kernel on a
|
||||
Sharp Zaurus SL-5600 (Poodle), SL-C700 (Corgi),
|
||||
SL-C750 (Shepherd), SL-C760 (Husky), SL-C1000 (Akita),
|
||||
SL-C3000 (Spitz) or SL-C3100 (Borzoi) handheld computer.
|
||||
SL-C3000 (Spitz), SL-C3100 (Borzoi) or SL-C6000x (Tosa)
|
||||
handheld computer.
|
||||
|
||||
endchoice
|
||||
|
||||
|
@ -37,7 +38,7 @@ choice
|
|||
prompt "Select target Sharp Zaurus device range"
|
||||
|
||||
config PXA_SHARPSL_25x
|
||||
bool "Sharp PXA25x models (SL-5600 and SL-C7xx)"
|
||||
bool "Sharp PXA25x models (SL-5600, SL-C7xx and SL-C6000x)"
|
||||
select PXA25x
|
||||
|
||||
config PXA_SHARPSL_27x
|
||||
|
@ -80,6 +81,10 @@ config MACH_BORZOI
|
|||
depends PXA_SHARPSL_27x
|
||||
select PXA_SHARP_Cxx00
|
||||
|
||||
config MACH_TOSA
|
||||
bool "Enable Sharp SL-6000x (Tosa) Support"
|
||||
depends PXA_SHARPSL
|
||||
|
||||
config PXA25x
|
||||
bool
|
||||
help
|
||||
|
|
|
@ -14,6 +14,7 @@ obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
|
|||
obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o ssp.o
|
||||
obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o ssp.o
|
||||
obj-$(CONFIG_MACH_POODLE) += poodle.o
|
||||
obj-$(CONFIG_MACH_TOSA) += tosa.o
|
||||
|
||||
# Support for blinky lights
|
||||
led-y := leds.o
|
||||
|
|
|
@ -19,16 +19,20 @@
|
|||
#include <linux/major.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/sizes.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/flash.h>
|
||||
|
||||
#include <asm/hardware/sa1111.h>
|
||||
|
||||
|
@ -199,10 +203,75 @@ static struct platform_device smc91x_device = {
|
|||
.resource = smc91x_resources,
|
||||
};
|
||||
|
||||
static struct resource flash_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x00000000,
|
||||
.end = SZ_64M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = 0x04000000,
|
||||
.end = 0x04000000 + SZ_64M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition lubbock_partitions[] = {
|
||||
{
|
||||
.name = "Bootloader",
|
||||
.size = 0x00040000,
|
||||
.offset = 0,
|
||||
.mask_flags = MTD_WRITEABLE /* force read-only */
|
||||
},{
|
||||
.name = "Kernel",
|
||||
.size = 0x00100000,
|
||||
.offset = 0x00040000,
|
||||
},{
|
||||
.name = "Filesystem",
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
.offset = 0x00140000
|
||||
}
|
||||
};
|
||||
|
||||
static struct flash_platform_data lubbock_flash_data[2] = {
|
||||
{
|
||||
.map_name = "cfi_probe",
|
||||
.parts = lubbock_partitions,
|
||||
.nr_parts = ARRAY_SIZE(lubbock_partitions),
|
||||
}, {
|
||||
.map_name = "cfi_probe",
|
||||
.parts = NULL,
|
||||
.nr_parts = 0,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device lubbock_flash_device[2] = {
|
||||
{
|
||||
.name = "pxa2xx-flash",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &lubbock_flash_data[0],
|
||||
},
|
||||
.resource = &flash_resources[0],
|
||||
.num_resources = 1,
|
||||
},
|
||||
{
|
||||
.name = "pxa2xx-flash",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.platform_data = &lubbock_flash_data[1],
|
||||
},
|
||||
.resource = &flash_resources[1],
|
||||
.num_resources = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
&sa1111_device,
|
||||
&lub_audio_device,
|
||||
&smc91x_device,
|
||||
&lubbock_flash_device[0],
|
||||
&lubbock_flash_device[1],
|
||||
};
|
||||
|
||||
static struct pxafb_mach_info sharp_lm8v31 __initdata = {
|
||||
|
@ -315,10 +384,21 @@ static struct pxaficp_platform_data lubbock_ficp_platform_data = {
|
|||
|
||||
static void __init lubbock_init(void)
|
||||
{
|
||||
int flashboot = (LUB_CONF_SWITCHES & 1);
|
||||
|
||||
pxa_set_udc_info(&udc_info);
|
||||
set_pxa_fb_info(&sharp_lm8v31);
|
||||
pxa_set_mci_info(&lubbock_mci_platform_data);
|
||||
pxa_set_ficp_info(&lubbock_ficp_platform_data);
|
||||
|
||||
lubbock_flash_data[0].width = lubbock_flash_data[1].width =
|
||||
(BOOT_DEF & 1) ? 2 : 4;
|
||||
/* Compensate for the nROMBT switch which swaps the flash banks */
|
||||
printk(KERN_NOTICE "Lubbock configured to boot from %s (bank %d)\n",
|
||||
flashboot?"Flash":"ROM", flashboot);
|
||||
|
||||
lubbock_flash_data[flashboot^1].name = "application-flash";
|
||||
lubbock_flash_data[flashboot].name = "boot-rom";
|
||||
(void) platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include <asm/types.h>
|
||||
#include <asm/setup.h>
|
||||
|
@ -27,10 +30,12 @@
|
|||
#include <asm/mach-types.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/sizes.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/flash.h>
|
||||
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
#include <asm/arch/mainstone.h>
|
||||
|
@ -190,6 +195,69 @@ static struct platform_device mst_audio_device = {
|
|||
.dev = { .platform_data = &mst_audio_ops },
|
||||
};
|
||||
|
||||
static struct resource flash_resources[] = {
|
||||
[0] = {
|
||||
.start = PXA_CS0_PHYS,
|
||||
.end = PXA_CS0_PHYS + SZ_64M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = PXA_CS1_PHYS,
|
||||
.end = PXA_CS1_PHYS + SZ_64M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition mainstoneflash0_partitions[] = {
|
||||
{
|
||||
.name = "Bootloader",
|
||||
.size = 0x00040000,
|
||||
.offset = 0,
|
||||
.mask_flags = MTD_WRITEABLE /* force read-only */
|
||||
},{
|
||||
.name = "Kernel",
|
||||
.size = 0x00400000,
|
||||
.offset = 0x00040000,
|
||||
},{
|
||||
.name = "Filesystem",
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
.offset = 0x00440000
|
||||
}
|
||||
};
|
||||
|
||||
static struct flash_platform_data mst_flash_data[2] = {
|
||||
{
|
||||
.map_name = "cfi_probe",
|
||||
.parts = mainstoneflash0_partitions,
|
||||
.nr_parts = ARRAY_SIZE(mainstoneflash0_partitions),
|
||||
}, {
|
||||
.map_name = "cfi_probe",
|
||||
.parts = NULL,
|
||||
.nr_parts = 0,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device mst_flash_device[2] = {
|
||||
{
|
||||
.name = "pxa2xx-flash",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &mst_flash_data[0],
|
||||
},
|
||||
.resource = &flash_resources[0],
|
||||
.num_resources = 1,
|
||||
},
|
||||
{
|
||||
.name = "pxa2xx-flash",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.platform_data = &mst_flash_data[1],
|
||||
},
|
||||
.resource = &flash_resources[1],
|
||||
.num_resources = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static void mainstone_backlight_power(int on)
|
||||
{
|
||||
if (on) {
|
||||
|
@ -318,16 +386,34 @@ static struct pxaficp_platform_data mainstone_ficp_platform_data = {
|
|||
.transceiver_mode = mainstone_irda_transceiver_mode,
|
||||
};
|
||||
|
||||
static struct platform_device *platform_devices[] __initdata = {
|
||||
&smc91x_device,
|
||||
&mst_audio_device,
|
||||
&mst_flash_device[0],
|
||||
&mst_flash_device[1],
|
||||
};
|
||||
|
||||
static void __init mainstone_init(void)
|
||||
{
|
||||
int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
|
||||
|
||||
mst_flash_data[0].width = (BOOT_DEF & 1) ? 2 : 4;
|
||||
mst_flash_data[1].width = 4;
|
||||
|
||||
/* Compensate for SW7 which swaps the flash banks */
|
||||
mst_flash_data[SW7].name = "processor-flash";
|
||||
mst_flash_data[SW7 ^ 1].name = "mainboard-flash";
|
||||
|
||||
printk(KERN_NOTICE "Mainstone configured to boot from %s\n",
|
||||
mst_flash_data[0].name);
|
||||
|
||||
/*
|
||||
* On Mainstone, we route AC97_SYSCLK via GPIO45 to
|
||||
* the audio daughter card
|
||||
*/
|
||||
pxa_gpio_mode(GPIO45_SYSCLK_AC97_MD);
|
||||
|
||||
platform_device_register(&smc91x_device);
|
||||
platform_device_register(&mst_audio_device);
|
||||
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
|
||||
|
||||
/* reading Mainstone's "Virtual Configuration Register"
|
||||
might be handy to select LCD type here */
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
#include <linux/config.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/time.h>
|
||||
|
@ -19,6 +20,7 @@
|
|||
#include <asm/hardware.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/arch/pm.h>
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
#include <asm/arch/lubbock.h>
|
||||
#include <asm/mach/time.h>
|
||||
|
@ -72,7 +74,7 @@ enum { SLEEP_SAVE_START = 0,
|
|||
};
|
||||
|
||||
|
||||
static int pxa_pm_enter(suspend_state_t state)
|
||||
int pxa_pm_enter(suspend_state_t state)
|
||||
{
|
||||
unsigned long sleep_save[SLEEP_SAVE_SIZE];
|
||||
unsigned long checksum = 0;
|
||||
|
@ -191,6 +193,8 @@ static int pxa_pm_enter(suspend_state_t state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(pxa_pm_enter);
|
||||
|
||||
unsigned long sleep_phys_sp(void *sp)
|
||||
{
|
||||
return virt_to_phys(sp);
|
||||
|
@ -199,21 +203,25 @@ unsigned long sleep_phys_sp(void *sp)
|
|||
/*
|
||||
* Called after processes are frozen, but before we shut down devices.
|
||||
*/
|
||||
static int pxa_pm_prepare(suspend_state_t state)
|
||||
int pxa_pm_prepare(suspend_state_t state)
|
||||
{
|
||||
extern int pxa_cpu_pm_prepare(suspend_state_t state);
|
||||
|
||||
return pxa_cpu_pm_prepare(state);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(pxa_pm_prepare);
|
||||
|
||||
/*
|
||||
* Called after devices are re-setup, but before processes are thawed.
|
||||
*/
|
||||
static int pxa_pm_finish(suspend_state_t state)
|
||||
int pxa_pm_finish(suspend_state_t state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(pxa_pm_finish);
|
||||
|
||||
/*
|
||||
* Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
|
||||
*/
|
||||
|
@ -230,4 +238,4 @@ static int __init pxa_pm_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
late_initcall(pxa_pm_init);
|
||||
device_initcall(pxa_pm_init);
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Support for Sharp SL-C6000x PDAs
|
||||
* Model: (Tosa)
|
||||
*
|
||||
* Copyright (c) 2005 Dirk Opfer
|
||||
*
|
||||
* Based on code written by Sharp/Lineo for 2.4 kernels
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mmc/host.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/arch/irda.h>
|
||||
#include <asm/arch/mmc.h>
|
||||
#include <asm/arch/udc.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
#include <asm/arch/irq.h>
|
||||
#include <asm/arch/tosa.h>
|
||||
|
||||
#include <asm/hardware/scoop.h>
|
||||
#include <asm/mach/sharpsl_param.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
|
||||
/*
|
||||
* SCOOP Device
|
||||
*/
|
||||
static struct resource tosa_scoop_resources[] = {
|
||||
[0] = {
|
||||
.start = TOSA_CF_PHYS,
|
||||
.end = TOSA_CF_PHYS + 0xfff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct scoop_config tosa_scoop_setup = {
|
||||
.io_dir = TOSA_SCOOP_IO_DIR,
|
||||
.io_out = TOSA_SCOOP_IO_OUT,
|
||||
|
||||
};
|
||||
|
||||
struct platform_device tosascoop_device = {
|
||||
.name = "sharp-scoop",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &tosa_scoop_setup,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(tosa_scoop_resources),
|
||||
.resource = tosa_scoop_resources,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* SCOOP Device Jacket
|
||||
*/
|
||||
static struct resource tosa_scoop_jc_resources[] = {
|
||||
[0] = {
|
||||
.start = TOSA_SCOOP_PHYS + 0x40,
|
||||
.end = TOSA_SCOOP_PHYS + 0xfff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct scoop_config tosa_scoop_jc_setup = {
|
||||
.io_dir = TOSA_SCOOP_JC_IO_DIR,
|
||||
.io_out = TOSA_SCOOP_JC_IO_OUT,
|
||||
};
|
||||
|
||||
struct platform_device tosascoop_jc_device = {
|
||||
.name = "sharp-scoop",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.platform_data = &tosa_scoop_jc_setup,
|
||||
.parent = &tosascoop_device.dev,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(tosa_scoop_jc_resources),
|
||||
.resource = tosa_scoop_jc_resources,
|
||||
};
|
||||
|
||||
static struct scoop_pcmcia_dev tosa_pcmcia_scoop[] = {
|
||||
{
|
||||
.dev = &tosascoop_device.dev,
|
||||
.irq = TOSA_IRQ_GPIO_CF_IRQ,
|
||||
.cd_irq = TOSA_IRQ_GPIO_CF_CD,
|
||||
.cd_irq_str = "PCMCIA0 CD",
|
||||
},{
|
||||
.dev = &tosascoop_jc_device.dev,
|
||||
.irq = TOSA_IRQ_GPIO_JC_CF_IRQ,
|
||||
.cd_irq = -1,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
&tosascoop_device,
|
||||
&tosascoop_jc_device,
|
||||
};
|
||||
|
||||
static void __init tosa_init(void)
|
||||
{
|
||||
pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_IN);
|
||||
pxa_gpio_mode(TOSA_GPIO_TC6393_INT | GPIO_IN);
|
||||
|
||||
/* setup sleep mode values */
|
||||
PWER = 0x00000002;
|
||||
PFER = 0x00000000;
|
||||
PRER = 0x00000002;
|
||||
PGSR0 = 0x00000000;
|
||||
PGSR1 = 0x00FF0002;
|
||||
PGSR2 = 0x00014000;
|
||||
PCFR |= PCFR_OPDE;
|
||||
|
||||
// enable batt_fault
|
||||
PMCR = 0x01;
|
||||
|
||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
|
||||
scoop_num = 2;
|
||||
scoop_devs = &tosa_pcmcia_scoop[0];
|
||||
}
|
||||
|
||||
static void __init fixup_tosa(struct machine_desc *desc,
|
||||
struct tag *tags, char **cmdline, struct meminfo *mi)
|
||||
{
|
||||
sharpsl_save_param();
|
||||
mi->nr_banks=1;
|
||||
mi->bank[0].start = 0xa0000000;
|
||||
mi->bank[0].node = 0;
|
||||
mi->bank[0].size = (64*1024*1024);
|
||||
}
|
||||
|
||||
MACHINE_START(TOSA, "SHARP Tosa")
|
||||
.phys_ram = 0xa0000000,
|
||||
.phys_io = 0x40000000,
|
||||
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
|
||||
.fixup = fixup_tosa,
|
||||
.map_io = pxa_map_io,
|
||||
.init_irq = pxa_init_irq,
|
||||
.init_machine = tosa_init,
|
||||
.timer = &pxa_timer,
|
||||
MACHINE_END
|
|
@ -250,6 +250,18 @@ config CPU_V6
|
|||
select CPU_COPY_V6
|
||||
select CPU_TLB_V6
|
||||
|
||||
# ARMv6k
|
||||
config CPU_32v6K
|
||||
bool "Support ARM V6K processor extensions" if !SMP
|
||||
depends on CPU_V6
|
||||
default y if SMP
|
||||
help
|
||||
Say Y here if your ARMv6 processor supports the 'K' extension.
|
||||
This enables the kernel to use some instructions not present
|
||||
on previous processors, and as such a kernel build with this
|
||||
enabled will not boot on processors with do not support these
|
||||
instructions.
|
||||
|
||||
# Figure out what processor architecture version we should be using.
|
||||
# This defines the compiler instruction set which depends on the machine type.
|
||||
config CPU_32v3
|
||||
|
|
|
@ -469,14 +469,14 @@ void __init create_mapping(struct map_desc *md)
|
|||
|
||||
if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
|
||||
printk(KERN_WARNING "BUG: not creating mapping for "
|
||||
"0x%016llx at 0x%08lx in user region\n",
|
||||
"0x%08llx at 0x%08lx in user region\n",
|
||||
__pfn_to_phys((u64)md->pfn), md->virtual);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
|
||||
md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
|
||||
printk(KERN_WARNING "BUG: mapping for 0x%016llx at 0x%08lx "
|
||||
printk(KERN_WARNING "BUG: mapping for 0x%08llx at 0x%08lx "
|
||||
"overlaps vmalloc space\n",
|
||||
__pfn_to_phys((u64)md->pfn), md->virtual);
|
||||
}
|
||||
|
@ -492,14 +492,14 @@ void __init create_mapping(struct map_desc *md)
|
|||
if(md->pfn >= 0x100000) {
|
||||
if(domain) {
|
||||
printk(KERN_ERR "MM: invalid domain in supersection "
|
||||
"mapping for 0x%016llx at 0x%08lx\n",
|
||||
"mapping for 0x%08llx at 0x%08lx\n",
|
||||
__pfn_to_phys((u64)md->pfn), md->virtual);
|
||||
return;
|
||||
}
|
||||
if((md->virtual | md->length | __pfn_to_phys(md->pfn))
|
||||
& ~SUPERSECTION_MASK) {
|
||||
printk(KERN_ERR "MM: cannot create mapping for "
|
||||
"0x%016llx at 0x%08lx invalid alignment\n",
|
||||
"0x%08llx at 0x%08lx invalid alignment\n",
|
||||
__pfn_to_phys((u64)md->pfn), md->virtual);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -108,8 +108,11 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
|
|||
/*
|
||||
* Sets the lazy trigger so that the next I/O operation will
|
||||
* reload the correct bitmap.
|
||||
* Reset the owner so that a process switch will not set
|
||||
* tss->io_bitmap_base to IO_BITMAP_OFFSET.
|
||||
*/
|
||||
tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
|
||||
tss->io_bitmap_owner = NULL;
|
||||
|
||||
put_cpu();
|
||||
|
||||
|
|
|
@ -300,6 +300,7 @@ config PPC_PMAC64
|
|||
bool
|
||||
depends on PPC_PMAC && POWER4
|
||||
select U3_DART
|
||||
select GENERIC_TBSYNC
|
||||
default y
|
||||
|
||||
config PPC_PREP
|
||||
|
@ -314,15 +315,17 @@ config PPC_MAPLE
|
|||
bool " Maple 970FX Evaluation Board"
|
||||
select U3_DART
|
||||
select MPIC_BROKEN_U3
|
||||
select GENERIC_TBSYNC
|
||||
default n
|
||||
help
|
||||
This option enables support for the Maple 970FX Evaluation Board.
|
||||
For more informations, refer to <http://www.970eval.com>
|
||||
|
||||
config PPC_BPA
|
||||
bool " Broadband Processor Architecture"
|
||||
config PPC_CELL
|
||||
bool " Cell Broadband Processor Architecture"
|
||||
depends on PPC_MULTIPLATFORM && PPC64
|
||||
select PPC_RTAS
|
||||
select MMIO_NVRAM
|
||||
|
||||
config PPC_OF
|
||||
bool
|
||||
|
@ -353,13 +356,26 @@ config RTAS_ERROR_LOGGING
|
|||
depends on PPC_RTAS
|
||||
default n
|
||||
|
||||
config RTAS_PROC
|
||||
bool "Proc interface to RTAS"
|
||||
depends on PPC_RTAS
|
||||
default y
|
||||
|
||||
config RTAS_FLASH
|
||||
tristate "Firmware flash interface"
|
||||
depends on PPC64 && RTAS_PROC
|
||||
|
||||
config MMIO_NVRAM
|
||||
bool
|
||||
default n
|
||||
|
||||
config MPIC_BROKEN_U3
|
||||
bool
|
||||
depends on PPC_MAPLE
|
||||
default y
|
||||
|
||||
config BPA_IIC
|
||||
depends on PPC_BPA
|
||||
config CELL_IIC
|
||||
depends on PPC_CELL
|
||||
bool
|
||||
default y
|
||||
|
||||
|
@ -372,6 +388,11 @@ config PPC_MPC106
|
|||
bool
|
||||
default n
|
||||
|
||||
config GENERIC_TBSYNC
|
||||
bool
|
||||
default y if CONFIG_PPC32 && CONFIG_SMP
|
||||
default n
|
||||
|
||||
source "drivers/cpufreq/Kconfig"
|
||||
|
||||
config CPU_FREQ_PMAC
|
||||
|
@ -582,6 +603,15 @@ config NODES_SPAN_OTHER_NODES
|
|||
def_bool y
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
|
||||
config PPC_64K_PAGES
|
||||
bool "64k page size"
|
||||
help
|
||||
This option changes the kernel logical page size to 64k. On machines
|
||||
without processor support for 64k pages, the kernel will simulate
|
||||
them by loading each individual 4k page on demand transparently,
|
||||
while on hardware with such support, it will be used to map
|
||||
normal application pages.
|
||||
|
||||
config SCHED_SMT
|
||||
bool "SMT (Hyperthreading) scheduler support"
|
||||
depends on PPC64 && SMP
|
||||
|
|
|
@ -12,9 +12,6 @@
|
|||
# Rewritten by Cort Dougan and Paul Mackerras
|
||||
#
|
||||
|
||||
# This must match PAGE_OFFSET in include/asm-powerpc/page.h.
|
||||
KERNELLOAD := $(CONFIG_KERNEL_START)
|
||||
|
||||
HAS_BIARCH := $(call cc-option-yn, -m32)
|
||||
|
||||
ifeq ($(CONFIG_PPC64),y)
|
||||
|
@ -59,7 +56,7 @@ override LD += -m elf$(SZ)ppc
|
|||
override CC += -m$(SZ)
|
||||
endif
|
||||
|
||||
LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic -e $(KERNELLOAD)
|
||||
LDFLAGS_vmlinux := -Bstatic
|
||||
|
||||
# The -Iarch/$(ARCH)/include is temporary while we are merging
|
||||
CPPFLAGS += -Iarch/$(ARCH) -Iarch/$(ARCH)/include
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,998 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.14-rc4
|
||||
# Thu Oct 20 08:30:56 2005
|
||||
#
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_MMU=y
|
||||
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
|
||||
CONFIG_GENERIC_CALIBRATE_DELAY=y
|
||||
CONFIG_GENERIC_ISA_DMA=y
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_COMPAT=y
|
||||
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
|
||||
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
|
||||
CONFIG_FORCE_MAX_ZONEORDER=13
|
||||
|
||||
#
|
||||
# Code maturity level options
|
||||
#
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_CLEAN_COMPILE=y
|
||||
CONFIG_LOCK_KERNEL=y
|
||||
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||
|
||||
#
|
||||
# General setup
|
||||
#
|
||||
CONFIG_LOCALVERSION=""
|
||||
CONFIG_LOCALVERSION_AUTO=y
|
||||
CONFIG_SWAP=y
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
# CONFIG_BSD_PROCESS_ACCT is not set
|
||||
CONFIG_SYSCTL=y
|
||||
CONFIG_AUDIT=y
|
||||
CONFIG_AUDITSYSCALL=y
|
||||
CONFIG_HOTPLUG=y
|
||||
CONFIG_KOBJECT_UEVENT=y
|
||||
CONFIG_IKCONFIG=y
|
||||
CONFIG_IKCONFIG_PROC=y
|
||||
# CONFIG_CPUSETS is not set
|
||||
CONFIG_INITRAMFS_SOURCE=""
|
||||
# CONFIG_EMBEDDED is not set
|
||||
CONFIG_KALLSYMS=y
|
||||
# CONFIG_KALLSYMS_ALL is not set
|
||||
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_BUG=y
|
||||
CONFIG_BASE_FULL=y
|
||||
CONFIG_FUTEX=y
|
||||
CONFIG_EPOLL=y
|
||||
CONFIG_SHMEM=y
|
||||
CONFIG_CC_ALIGN_FUNCTIONS=0
|
||||
CONFIG_CC_ALIGN_LABELS=0
|
||||
CONFIG_CC_ALIGN_LOOPS=0
|
||||
CONFIG_CC_ALIGN_JUMPS=0
|
||||
# CONFIG_TINY_SHMEM is not set
|
||||
CONFIG_BASE_SMALL=0
|
||||
|
||||
#
|
||||
# Loadable module support
|
||||
#
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
# CONFIG_MODULE_FORCE_UNLOAD is not set
|
||||
CONFIG_OBSOLETE_MODPARM=y
|
||||
CONFIG_MODVERSIONS=y
|
||||
CONFIG_MODULE_SRCVERSION_ALL=y
|
||||
CONFIG_KMOD=y
|
||||
CONFIG_STOP_MACHINE=y
|
||||
CONFIG_SYSVIPC_COMPAT=y
|
||||
|
||||
#
|
||||
# Platform support
|
||||
#
|
||||
CONFIG_PPC_ISERIES=y
|
||||
# CONFIG_PPC_MULTIPLATFORM is not set
|
||||
CONFIG_PPC=y
|
||||
CONFIG_PPC64=y
|
||||
CONFIG_IBMVIO=y
|
||||
# CONFIG_POWER4_ONLY is not set
|
||||
CONFIG_IOMMU_VMERGE=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=32
|
||||
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
|
||||
CONFIG_ARCH_FLATMEM_ENABLE=y
|
||||
CONFIG_SELECT_MEMORY_MODEL=y
|
||||
CONFIG_FLATMEM_MANUAL=y
|
||||
# CONFIG_DISCONTIGMEM_MANUAL is not set
|
||||
# CONFIG_SPARSEMEM_MANUAL is not set
|
||||
CONFIG_FLATMEM=y
|
||||
CONFIG_FLAT_NODE_MEM_MAP=y
|
||||
# CONFIG_SPARSEMEM_STATIC is not set
|
||||
# CONFIG_NUMA is not set
|
||||
# CONFIG_SCHED_SMT is not set
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
# CONFIG_PREEMPT_VOLUNTARY is not set
|
||||
# CONFIG_PREEMPT is not set
|
||||
# CONFIG_PREEMPT_BKL is not set
|
||||
# CONFIG_HZ_100 is not set
|
||||
CONFIG_HZ_250=y
|
||||
# CONFIG_HZ_1000 is not set
|
||||
CONFIG_HZ=250
|
||||
CONFIG_GENERIC_HARDIRQS=y
|
||||
CONFIG_LPARCFG=y
|
||||
CONFIG_SECCOMP=y
|
||||
CONFIG_BINFMT_ELF=y
|
||||
# CONFIG_BINFMT_MISC is not set
|
||||
CONFIG_ISA_DMA_API=y
|
||||
|
||||
#
|
||||
# Bus Options
|
||||
#
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCI_DOMAINS=y
|
||||
CONFIG_PCI_LEGACY_PROC=y
|
||||
# CONFIG_PCI_DEBUG is not set
|
||||
|
||||
#
|
||||
# PCCARD (PCMCIA/CardBus) support
|
||||
#
|
||||
# CONFIG_PCCARD is not set
|
||||
|
||||
#
|
||||
# PCI Hotplug Support
|
||||
#
|
||||
# CONFIG_HOTPLUG_PCI is not set
|
||||
|
||||
#
|
||||
# Networking
|
||||
#
|
||||
CONFIG_NET=y
|
||||
|
||||
#
|
||||
# Networking options
|
||||
#
|
||||
CONFIG_PACKET=y
|
||||
# CONFIG_PACKET_MMAP is not set
|
||||
CONFIG_UNIX=y
|
||||
CONFIG_XFRM=y
|
||||
CONFIG_XFRM_USER=m
|
||||
CONFIG_NET_KEY=m
|
||||
CONFIG_INET=y
|
||||
CONFIG_IP_MULTICAST=y
|
||||
# CONFIG_IP_ADVANCED_ROUTER is not set
|
||||
CONFIG_IP_FIB_HASH=y
|
||||
# CONFIG_IP_PNP is not set
|
||||
CONFIG_NET_IPIP=y
|
||||
# CONFIG_NET_IPGRE is not set
|
||||
# CONFIG_IP_MROUTE is not set
|
||||
# CONFIG_ARPD is not set
|
||||
CONFIG_SYN_COOKIES=y
|
||||
CONFIG_INET_AH=m
|
||||
CONFIG_INET_ESP=m
|
||||
CONFIG_INET_IPCOMP=m
|
||||
CONFIG_INET_TUNNEL=y
|
||||
CONFIG_INET_DIAG=y
|
||||
CONFIG_INET_TCP_DIAG=y
|
||||
# CONFIG_TCP_CONG_ADVANCED is not set
|
||||
CONFIG_TCP_CONG_BIC=y
|
||||
|
||||
#
|
||||
# IP: Virtual Server Configuration
|
||||
#
|
||||
# CONFIG_IP_VS is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
CONFIG_NETFILTER=y
|
||||
# CONFIG_NETFILTER_DEBUG is not set
|
||||
# CONFIG_NETFILTER_NETLINK is not set
|
||||
|
||||
#
|
||||
# IP: Netfilter Configuration
|
||||
#
|
||||
CONFIG_IP_NF_CONNTRACK=m
|
||||
CONFIG_IP_NF_CT_ACCT=y
|
||||
CONFIG_IP_NF_CONNTRACK_MARK=y
|
||||
CONFIG_IP_NF_CONNTRACK_EVENTS=y
|
||||
CONFIG_IP_NF_CT_PROTO_SCTP=m
|
||||
CONFIG_IP_NF_FTP=m
|
||||
CONFIG_IP_NF_IRC=m
|
||||
# CONFIG_IP_NF_NETBIOS_NS is not set
|
||||
CONFIG_IP_NF_TFTP=m
|
||||
CONFIG_IP_NF_AMANDA=m
|
||||
# CONFIG_IP_NF_PPTP is not set
|
||||
CONFIG_IP_NF_QUEUE=m
|
||||
CONFIG_IP_NF_IPTABLES=m
|
||||
CONFIG_IP_NF_MATCH_LIMIT=m
|
||||
CONFIG_IP_NF_MATCH_IPRANGE=m
|
||||
CONFIG_IP_NF_MATCH_MAC=m
|
||||
CONFIG_IP_NF_MATCH_PKTTYPE=m
|
||||
CONFIG_IP_NF_MATCH_MARK=m
|
||||
CONFIG_IP_NF_MATCH_MULTIPORT=m
|
||||
CONFIG_IP_NF_MATCH_TOS=m
|
||||
CONFIG_IP_NF_MATCH_RECENT=m
|
||||
CONFIG_IP_NF_MATCH_ECN=m
|
||||
CONFIG_IP_NF_MATCH_DSCP=m
|
||||
CONFIG_IP_NF_MATCH_AH_ESP=m
|
||||
CONFIG_IP_NF_MATCH_LENGTH=m
|
||||
CONFIG_IP_NF_MATCH_TTL=m
|
||||
CONFIG_IP_NF_MATCH_TCPMSS=m
|
||||
CONFIG_IP_NF_MATCH_HELPER=m
|
||||
CONFIG_IP_NF_MATCH_STATE=m
|
||||
CONFIG_IP_NF_MATCH_CONNTRACK=m
|
||||
CONFIG_IP_NF_MATCH_OWNER=m
|
||||
CONFIG_IP_NF_MATCH_ADDRTYPE=m
|
||||
CONFIG_IP_NF_MATCH_REALM=m
|
||||
CONFIG_IP_NF_MATCH_SCTP=m
|
||||
# CONFIG_IP_NF_MATCH_DCCP is not set
|
||||
CONFIG_IP_NF_MATCH_COMMENT=m
|
||||
CONFIG_IP_NF_MATCH_CONNMARK=m
|
||||
CONFIG_IP_NF_MATCH_CONNBYTES=m
|
||||
CONFIG_IP_NF_MATCH_HASHLIMIT=m
|
||||
CONFIG_IP_NF_MATCH_STRING=m
|
||||
CONFIG_IP_NF_FILTER=m
|
||||
CONFIG_IP_NF_TARGET_REJECT=m
|
||||
CONFIG_IP_NF_TARGET_LOG=m
|
||||
CONFIG_IP_NF_TARGET_ULOG=m
|
||||
CONFIG_IP_NF_TARGET_TCPMSS=m
|
||||
CONFIG_IP_NF_TARGET_NFQUEUE=m
|
||||
CONFIG_IP_NF_NAT=m
|
||||
CONFIG_IP_NF_NAT_NEEDED=y
|
||||
CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_SAME=m
|
||||
CONFIG_IP_NF_NAT_SNMP_BASIC=m
|
||||
CONFIG_IP_NF_NAT_IRC=m
|
||||
CONFIG_IP_NF_NAT_FTP=m
|
||||
CONFIG_IP_NF_NAT_TFTP=m
|
||||
CONFIG_IP_NF_NAT_AMANDA=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP_NF_TARGET_TOS=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_DSCP=m
|
||||
CONFIG_IP_NF_TARGET_MARK=m
|
||||
CONFIG_IP_NF_TARGET_CLASSIFY=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_TARGET_CONNMARK=m
|
||||
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
CONFIG_IP_NF_TARGET_NOTRACK=m
|
||||
CONFIG_IP_NF_ARPTABLES=m
|
||||
CONFIG_IP_NF_ARPFILTER=m
|
||||
CONFIG_IP_NF_ARP_MANGLE=m
|
||||
|
||||
#
|
||||
# DCCP Configuration (EXPERIMENTAL)
|
||||
#
|
||||
# CONFIG_IP_DCCP is not set
|
||||
|
||||
#
|
||||
# SCTP Configuration (EXPERIMENTAL)
|
||||
#
|
||||
# CONFIG_IP_SCTP is not set
|
||||
# CONFIG_ATM is not set
|
||||
# CONFIG_BRIDGE is not set
|
||||
# CONFIG_VLAN_8021Q is not set
|
||||
# CONFIG_DECNET is not set
|
||||
CONFIG_LLC=y
|
||||
# CONFIG_LLC2 is not set
|
||||
# CONFIG_IPX is not set
|
||||
# CONFIG_ATALK is not set
|
||||
# CONFIG_X25 is not set
|
||||
# CONFIG_LAPB is not set
|
||||
# CONFIG_NET_DIVERT is not set
|
||||
# CONFIG_ECONET is not set
|
||||
# CONFIG_WAN_ROUTER is not set
|
||||
# CONFIG_NET_SCHED is not set
|
||||
CONFIG_NET_CLS_ROUTE=y
|
||||
|
||||
#
|
||||
# Network testing
|
||||
#
|
||||
# CONFIG_NET_PKTGEN is not set
|
||||
# CONFIG_HAMRADIO is not set
|
||||
# CONFIG_IRDA is not set
|
||||
# CONFIG_BT is not set
|
||||
# CONFIG_IEEE80211 is not set
|
||||
|
||||
#
|
||||
# Device Drivers
|
||||
#
|
||||
|
||||
#
|
||||
# Generic Driver Options
|
||||
#
|
||||
CONFIG_STANDALONE=y
|
||||
CONFIG_PREVENT_FIRMWARE_BUILD=y
|
||||
CONFIG_FW_LOADER=m
|
||||
# CONFIG_DEBUG_DRIVER is not set
|
||||
|
||||
#
|
||||
# Connector - unified userspace <-> kernelspace linker
|
||||
#
|
||||
# CONFIG_CONNECTOR is not set
|
||||
|
||||
#
|
||||
# Memory Technology Devices (MTD)
|
||||
#
|
||||
# CONFIG_MTD is not set
|
||||
|
||||
#
|
||||
# Parallel port support
|
||||
#
|
||||
# CONFIG_PARPORT is not set
|
||||
|
||||
#
|
||||
# Plug and Play support
|
||||
#
|
||||
|
||||
#
|
||||
# Block devices
|
||||
#
|
||||
# CONFIG_BLK_DEV_FD is not set
|
||||
# CONFIG_BLK_CPQ_DA is not set
|
||||
# CONFIG_BLK_CPQ_CISS_DA is not set
|
||||
# CONFIG_BLK_DEV_DAC960 is not set
|
||||
# CONFIG_BLK_DEV_UMEM is not set
|
||||
# CONFIG_BLK_DEV_COW_COMMON is not set
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
|
||||
CONFIG_BLK_DEV_NBD=m
|
||||
# CONFIG_BLK_DEV_SX8 is not set
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_COUNT=16
|
||||
CONFIG_BLK_DEV_RAM_SIZE=65536
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
# CONFIG_CDROM_PKTCDVD is not set
|
||||
|
||||
#
|
||||
# IO Schedulers
|
||||
#
|
||||
CONFIG_IOSCHED_NOOP=y
|
||||
CONFIG_IOSCHED_AS=y
|
||||
CONFIG_IOSCHED_DEADLINE=y
|
||||
CONFIG_IOSCHED_CFQ=y
|
||||
# CONFIG_ATA_OVER_ETH is not set
|
||||
|
||||
#
|
||||
# ATA/ATAPI/MFM/RLL support
|
||||
#
|
||||
# CONFIG_IDE is not set
|
||||
|
||||
#
|
||||
# SCSI device support
|
||||
#
|
||||
# CONFIG_RAID_ATTRS is not set
|
||||
CONFIG_SCSI=y
|
||||
CONFIG_SCSI_PROC_FS=y
|
||||
|
||||
#
|
||||
# SCSI support type (disk, tape, CD-ROM)
|
||||
#
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_CHR_DEV_ST=y
|
||||
# CONFIG_CHR_DEV_OSST is not set
|
||||
CONFIG_BLK_DEV_SR=y
|
||||
CONFIG_BLK_DEV_SR_VENDOR=y
|
||||
CONFIG_CHR_DEV_SG=y
|
||||
# CONFIG_CHR_DEV_SCH is not set
|
||||
|
||||
#
|
||||
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
|
||||
#
|
||||
CONFIG_SCSI_MULTI_LUN=y
|
||||
CONFIG_SCSI_CONSTANTS=y
|
||||
# CONFIG_SCSI_LOGGING is not set
|
||||
|
||||
#
|
||||
# SCSI Transport Attributes
|
||||
#
|
||||
CONFIG_SCSI_SPI_ATTRS=y
|
||||
CONFIG_SCSI_FC_ATTRS=y
|
||||
# CONFIG_SCSI_ISCSI_ATTRS is not set
|
||||
# CONFIG_SCSI_SAS_ATTRS is not set
|
||||
|
||||
#
|
||||
# SCSI low-level drivers
|
||||
#
|
||||
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
|
||||
# CONFIG_SCSI_3W_9XXX is not set
|
||||
# CONFIG_SCSI_ACARD is not set
|
||||
# CONFIG_SCSI_AACRAID is not set
|
||||
# CONFIG_SCSI_AIC7XXX is not set
|
||||
# CONFIG_SCSI_AIC7XXX_OLD is not set
|
||||
# CONFIG_SCSI_AIC79XX is not set
|
||||
# CONFIG_MEGARAID_NEWGEN is not set
|
||||
# CONFIG_MEGARAID_LEGACY is not set
|
||||
# CONFIG_MEGARAID_SAS is not set
|
||||
# CONFIG_SCSI_SATA is not set
|
||||
# CONFIG_SCSI_BUSLOGIC is not set
|
||||
# CONFIG_SCSI_DMX3191D is not set
|
||||
# CONFIG_SCSI_EATA is not set
|
||||
# CONFIG_SCSI_FUTURE_DOMAIN is not set
|
||||
# CONFIG_SCSI_GDTH is not set
|
||||
# CONFIG_SCSI_IPS is not set
|
||||
CONFIG_SCSI_IBMVSCSI=m
|
||||
# CONFIG_SCSI_INITIO is not set
|
||||
# CONFIG_SCSI_INIA100 is not set
|
||||
# CONFIG_SCSI_SYM53C8XX_2 is not set
|
||||
# CONFIG_SCSI_IPR is not set
|
||||
# CONFIG_SCSI_QLOGIC_FC is not set
|
||||
# CONFIG_SCSI_QLOGIC_1280 is not set
|
||||
CONFIG_SCSI_QLA2XXX=y
|
||||
# CONFIG_SCSI_QLA21XX is not set
|
||||
# CONFIG_SCSI_QLA22XX is not set
|
||||
# CONFIG_SCSI_QLA2300 is not set
|
||||
# CONFIG_SCSI_QLA2322 is not set
|
||||
# CONFIG_SCSI_QLA6312 is not set
|
||||
# CONFIG_SCSI_QLA24XX is not set
|
||||
# CONFIG_SCSI_LPFC is not set
|
||||
# CONFIG_SCSI_DC395x is not set
|
||||
# CONFIG_SCSI_DC390T is not set
|
||||
# CONFIG_SCSI_DEBUG is not set
|
||||
|
||||
#
|
||||
# Multi-device support (RAID and LVM)
|
||||
#
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_MD=y
|
||||
CONFIG_MD_LINEAR=y
|
||||
CONFIG_MD_RAID0=y
|
||||
CONFIG_MD_RAID1=y
|
||||
CONFIG_MD_RAID10=m
|
||||
CONFIG_MD_RAID5=y
|
||||
CONFIG_MD_RAID6=m
|
||||
CONFIG_MD_MULTIPATH=m
|
||||
CONFIG_MD_FAULTY=m
|
||||
CONFIG_BLK_DEV_DM=y
|
||||
CONFIG_DM_CRYPT=m
|
||||
CONFIG_DM_SNAPSHOT=m
|
||||
CONFIG_DM_MIRROR=m
|
||||
CONFIG_DM_ZERO=m
|
||||
# CONFIG_DM_MULTIPATH is not set
|
||||
|
||||
#
|
||||
# Fusion MPT device support
|
||||
#
|
||||
# CONFIG_FUSION is not set
|
||||
# CONFIG_FUSION_SPI is not set
|
||||
# CONFIG_FUSION_FC is not set
|
||||
# CONFIG_FUSION_SAS is not set
|
||||
|
||||
#
|
||||
# IEEE 1394 (FireWire) support
|
||||
#
|
||||
# CONFIG_IEEE1394 is not set
|
||||
|
||||
#
|
||||
# I2O device support
|
||||
#
|
||||
# CONFIG_I2O is not set
|
||||
|
||||
#
|
||||
# Macintosh device drivers
|
||||
#
|
||||
|
||||
#
|
||||
# Network device support
|
||||
#
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_DUMMY=m
|
||||
CONFIG_BONDING=m
|
||||
# CONFIG_EQUALIZER is not set
|
||||
CONFIG_TUN=m
|
||||
|
||||
#
|
||||
# ARCnet devices
|
||||
#
|
||||
# CONFIG_ARCNET is not set
|
||||
|
||||
#
|
||||
# PHY device support
|
||||
#
|
||||
# CONFIG_PHYLIB is not set
|
||||
|
||||
#
|
||||
# Ethernet (10 or 100Mbit)
|
||||
#
|
||||
CONFIG_NET_ETHERNET=y
|
||||
CONFIG_MII=y
|
||||
# CONFIG_HAPPYMEAL is not set
|
||||
# CONFIG_SUNGEM is not set
|
||||
# CONFIG_CASSINI is not set
|
||||
# CONFIG_NET_VENDOR_3COM is not set
|
||||
|
||||
#
|
||||
# Tulip family network device support
|
||||
#
|
||||
# CONFIG_NET_TULIP is not set
|
||||
# CONFIG_HP100 is not set
|
||||
CONFIG_NET_PCI=y
|
||||
CONFIG_PCNET32=y
|
||||
# CONFIG_AMD8111_ETH is not set
|
||||
# CONFIG_ADAPTEC_STARFIRE is not set
|
||||
# CONFIG_B44 is not set
|
||||
# CONFIG_FORCEDETH is not set
|
||||
# CONFIG_DGRS is not set
|
||||
# CONFIG_EEPRO100 is not set
|
||||
CONFIG_E100=y
|
||||
# CONFIG_FEALNX is not set
|
||||
# CONFIG_NATSEMI is not set
|
||||
# CONFIG_NE2K_PCI is not set
|
||||
# CONFIG_8139CP is not set
|
||||
# CONFIG_8139TOO is not set
|
||||
# CONFIG_SIS900 is not set
|
||||
# CONFIG_EPIC100 is not set
|
||||
# CONFIG_SUNDANCE is not set
|
||||
# CONFIG_VIA_RHINE is not set
|
||||
|
||||
#
|
||||
# Ethernet (1000 Mbit)
|
||||
#
|
||||
CONFIG_ACENIC=m
|
||||
# CONFIG_ACENIC_OMIT_TIGON_I is not set
|
||||
# CONFIG_DL2K is not set
|
||||
CONFIG_E1000=m
|
||||
# CONFIG_E1000_NAPI is not set
|
||||
# CONFIG_NS83820 is not set
|
||||
# CONFIG_HAMACHI is not set
|
||||
# CONFIG_YELLOWFIN is not set
|
||||
# CONFIG_R8169 is not set
|
||||
# CONFIG_SIS190 is not set
|
||||
# CONFIG_SKGE is not set
|
||||
# CONFIG_SK98LIN is not set
|
||||
# CONFIG_VIA_VELOCITY is not set
|
||||
# CONFIG_TIGON3 is not set
|
||||
# CONFIG_BNX2 is not set
|
||||
|
||||
#
|
||||
# Ethernet (10000 Mbit)
|
||||
#
|
||||
# CONFIG_CHELSIO_T1 is not set
|
||||
# CONFIG_IXGB is not set
|
||||
# CONFIG_S2IO is not set
|
||||
|
||||
#
|
||||
# Token Ring devices
|
||||
#
|
||||
CONFIG_TR=y
|
||||
CONFIG_IBMOL=y
|
||||
# CONFIG_3C359 is not set
|
||||
# CONFIG_TMS380TR is not set
|
||||
|
||||
#
|
||||
# Wireless LAN (non-hamradio)
|
||||
#
|
||||
# CONFIG_NET_RADIO is not set
|
||||
|
||||
#
|
||||
# Wan interfaces
|
||||
#
|
||||
# CONFIG_WAN is not set
|
||||
CONFIG_ISERIES_VETH=y
|
||||
# CONFIG_FDDI is not set
|
||||
# CONFIG_HIPPI is not set
|
||||
CONFIG_PPP=m
|
||||
# CONFIG_PPP_MULTILINK is not set
|
||||
# CONFIG_PPP_FILTER is not set
|
||||
CONFIG_PPP_ASYNC=m
|
||||
CONFIG_PPP_SYNC_TTY=m
|
||||
CONFIG_PPP_DEFLATE=m
|
||||
CONFIG_PPP_BSDCOMP=m
|
||||
CONFIG_PPPOE=m
|
||||
# CONFIG_SLIP is not set
|
||||
# CONFIG_NET_FC is not set
|
||||
# CONFIG_SHAPER is not set
|
||||
CONFIG_NETCONSOLE=y
|
||||
CONFIG_NETPOLL=y
|
||||
CONFIG_NETPOLL_RX=y
|
||||
CONFIG_NETPOLL_TRAP=y
|
||||
CONFIG_NET_POLL_CONTROLLER=y
|
||||
|
||||
#
|
||||
# ISDN subsystem
|
||||
#
|
||||
# CONFIG_ISDN is not set
|
||||
|
||||
#
|
||||
# Telephony Support
|
||||
#
|
||||
# CONFIG_PHONE is not set
|
||||
|
||||
#
|
||||
# Input device support
|
||||
#
|
||||
CONFIG_INPUT=y
|
||||
|
||||
#
|
||||
# Userland interfaces
|
||||
#
|
||||
CONFIG_INPUT_MOUSEDEV=y
|
||||
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
|
||||
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
|
||||
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
|
||||
# CONFIG_INPUT_JOYDEV is not set
|
||||
# CONFIG_INPUT_TSDEV is not set
|
||||
# CONFIG_INPUT_EVDEV is not set
|
||||
# CONFIG_INPUT_EVBUG is not set
|
||||
|
||||
#
|
||||
# Input Device Drivers
|
||||
#
|
||||
# CONFIG_INPUT_KEYBOARD is not set
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
# CONFIG_INPUT_JOYSTICK is not set
|
||||
# CONFIG_INPUT_TOUCHSCREEN is not set
|
||||
# CONFIG_INPUT_MISC is not set
|
||||
|
||||
#
|
||||
# Hardware I/O ports
|
||||
#
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_GAMEPORT is not set
|
||||
|
||||
#
|
||||
# Character devices
|
||||
#
|
||||
# CONFIG_SERIAL_NONSTANDARD is not set
|
||||
|
||||
#
|
||||
# Serial drivers
|
||||
#
|
||||
# CONFIG_SERIAL_8250 is not set
|
||||
|
||||
#
|
||||
# Non-8250 serial port support
|
||||
#
|
||||
CONFIG_SERIAL_CORE=m
|
||||
CONFIG_SERIAL_ICOM=m
|
||||
# CONFIG_SERIAL_JSM is not set
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
CONFIG_LEGACY_PTYS=y
|
||||
CONFIG_LEGACY_PTY_COUNT=256
|
||||
|
||||
#
|
||||
# IPMI
|
||||
#
|
||||
# CONFIG_IPMI_HANDLER is not set
|
||||
|
||||
#
|
||||
# Watchdog Cards
|
||||
#
|
||||
# CONFIG_WATCHDOG is not set
|
||||
# CONFIG_RTC is not set
|
||||
# CONFIG_DTLK is not set
|
||||
# CONFIG_R3964 is not set
|
||||
# CONFIG_APPLICOM is not set
|
||||
|
||||
#
|
||||
# Ftape, the floppy tape device driver
|
||||
#
|
||||
# CONFIG_AGP is not set
|
||||
# CONFIG_DRM is not set
|
||||
CONFIG_RAW_DRIVER=y
|
||||
CONFIG_MAX_RAW_DEVS=256
|
||||
# CONFIG_HANGCHECK_TIMER is not set
|
||||
|
||||
#
|
||||
# TPM devices
|
||||
#
|
||||
# CONFIG_TCG_TPM is not set
|
||||
|
||||
#
|
||||
# I2C support
|
||||
#
|
||||
# CONFIG_I2C is not set
|
||||
|
||||
#
|
||||
# Dallas's 1-wire bus
|
||||
#
|
||||
# CONFIG_W1 is not set
|
||||
|
||||
#
|
||||
# Hardware Monitoring support
|
||||
#
|
||||
# CONFIG_HWMON is not set
|
||||
# CONFIG_HWMON_VID is not set
|
||||
|
||||
#
|
||||
# Misc devices
|
||||
#
|
||||
|
||||
#
|
||||
# Multimedia Capabilities Port drivers
|
||||
#
|
||||
|
||||
#
|
||||
# Multimedia devices
|
||||
#
|
||||
# CONFIG_VIDEO_DEV is not set
|
||||
|
||||
#
|
||||
# Digital Video Broadcasting Devices
|
||||
#
|
||||
# CONFIG_DVB is not set
|
||||
|
||||
#
|
||||
# Graphics support
|
||||
#
|
||||
# CONFIG_FB is not set
|
||||
|
||||
#
|
||||
# Sound
|
||||
#
|
||||
# CONFIG_SOUND is not set
|
||||
|
||||
#
|
||||
# USB support
|
||||
#
|
||||
CONFIG_USB_ARCH_HAS_HCD=y
|
||||
CONFIG_USB_ARCH_HAS_OHCI=y
|
||||
# CONFIG_USB is not set
|
||||
|
||||
#
|
||||
# USB Gadget Support
|
||||
#
|
||||
# CONFIG_USB_GADGET is not set
|
||||
|
||||
#
|
||||
# MMC/SD Card support
|
||||
#
|
||||
# CONFIG_MMC is not set
|
||||
|
||||
#
|
||||
# InfiniBand support
|
||||
#
|
||||
# CONFIG_INFINIBAND is not set
|
||||
|
||||
#
|
||||
# SN Devices
|
||||
#
|
||||
|
||||
#
|
||||
# File systems
|
||||
#
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT2_FS_XATTR=y
|
||||
CONFIG_EXT2_FS_POSIX_ACL=y
|
||||
CONFIG_EXT2_FS_SECURITY=y
|
||||
CONFIG_EXT2_FS_XIP=y
|
||||
CONFIG_FS_XIP=y
|
||||
CONFIG_EXT3_FS=y
|
||||
CONFIG_EXT3_FS_XATTR=y
|
||||
CONFIG_EXT3_FS_POSIX_ACL=y
|
||||
CONFIG_EXT3_FS_SECURITY=y
|
||||
CONFIG_JBD=y
|
||||
# CONFIG_JBD_DEBUG is not set
|
||||
CONFIG_FS_MBCACHE=y
|
||||
CONFIG_REISERFS_FS=y
|
||||
# CONFIG_REISERFS_CHECK is not set
|
||||
# CONFIG_REISERFS_PROC_INFO is not set
|
||||
CONFIG_REISERFS_FS_XATTR=y
|
||||
CONFIG_REISERFS_FS_POSIX_ACL=y
|
||||
CONFIG_REISERFS_FS_SECURITY=y
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_JFS_POSIX_ACL=y
|
||||
CONFIG_JFS_SECURITY=y
|
||||
# CONFIG_JFS_DEBUG is not set
|
||||
# CONFIG_JFS_STATISTICS is not set
|
||||
CONFIG_FS_POSIX_ACL=y
|
||||
CONFIG_XFS_FS=m
|
||||
CONFIG_XFS_EXPORT=y
|
||||
# CONFIG_XFS_QUOTA is not set
|
||||
CONFIG_XFS_SECURITY=y
|
||||
CONFIG_XFS_POSIX_ACL=y
|
||||
# CONFIG_XFS_RT is not set
|
||||
# CONFIG_MINIX_FS is not set
|
||||
# CONFIG_ROMFS_FS is not set
|
||||
CONFIG_INOTIFY=y
|
||||
# CONFIG_QUOTA is not set
|
||||
CONFIG_DNOTIFY=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
# CONFIG_AUTOFS4_FS is not set
|
||||
# CONFIG_FUSE_FS is not set
|
||||
|
||||
#
|
||||
# CD-ROM/DVD Filesystems
|
||||
#
|
||||
CONFIG_ISO9660_FS=y
|
||||
CONFIG_JOLIET=y
|
||||
CONFIG_ZISOFS=y
|
||||
CONFIG_ZISOFS_FS=y
|
||||
CONFIG_UDF_FS=m
|
||||
CONFIG_UDF_NLS=y
|
||||
|
||||
#
|
||||
# DOS/FAT/NT Filesystems
|
||||
#
|
||||
CONFIG_FAT_FS=y
|
||||
CONFIG_MSDOS_FS=y
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_FAT_DEFAULT_CODEPAGE=437
|
||||
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
|
||||
# CONFIG_NTFS_FS is not set
|
||||
|
||||
#
|
||||
# Pseudo filesystems
|
||||
#
|
||||
CONFIG_PROC_FS=y
|
||||
CONFIG_PROC_KCORE=y
|
||||
CONFIG_SYSFS=y
|
||||
CONFIG_TMPFS=y
|
||||
# CONFIG_HUGETLBFS is not set
|
||||
# CONFIG_HUGETLB_PAGE is not set
|
||||
CONFIG_RAMFS=y
|
||||
# CONFIG_RELAYFS_FS is not set
|
||||
|
||||
#
|
||||
# Miscellaneous filesystems
|
||||
#
|
||||
# CONFIG_ADFS_FS is not set
|
||||
# CONFIG_AFFS_FS is not set
|
||||
# CONFIG_HFS_FS is not set
|
||||
# CONFIG_HFSPLUS_FS is not set
|
||||
# CONFIG_BEFS_FS is not set
|
||||
# CONFIG_BFS_FS is not set
|
||||
# CONFIG_EFS_FS is not set
|
||||
CONFIG_CRAMFS=y
|
||||
# CONFIG_VXFS_FS is not set
|
||||
# CONFIG_HPFS_FS is not set
|
||||
# CONFIG_QNX4FS_FS is not set
|
||||
# CONFIG_SYSV_FS is not set
|
||||
# CONFIG_UFS_FS is not set
|
||||
|
||||
#
|
||||
# Network File Systems
|
||||
#
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFS_V4=y
|
||||
# CONFIG_NFS_DIRECTIO is not set
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V2_ACL=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NFSD_V3_ACL=y
|
||||
CONFIG_NFSD_V4=y
|
||||
CONFIG_NFSD_TCP=y
|
||||
CONFIG_LOCKD=y
|
||||
CONFIG_LOCKD_V4=y
|
||||
CONFIG_EXPORTFS=m
|
||||
CONFIG_NFS_ACL_SUPPORT=y
|
||||
CONFIG_NFS_COMMON=y
|
||||
CONFIG_SUNRPC=y
|
||||
CONFIG_SUNRPC_GSS=y
|
||||
CONFIG_RPCSEC_GSS_KRB5=y
|
||||
CONFIG_RPCSEC_GSS_SPKM3=m
|
||||
# CONFIG_SMB_FS is not set
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS is not set
|
||||
CONFIG_CIFS_XATTR=y
|
||||
CONFIG_CIFS_POSIX=y
|
||||
# CONFIG_CIFS_EXPERIMENTAL is not set
|
||||
# CONFIG_NCP_FS is not set
|
||||
# CONFIG_CODA_FS is not set
|
||||
# CONFIG_AFS_FS is not set
|
||||
# CONFIG_9P_FS is not set
|
||||
|
||||
#
|
||||
# Partition Types
|
||||
#
|
||||
# CONFIG_PARTITION_ADVANCED is not set
|
||||
CONFIG_MSDOS_PARTITION=y
|
||||
|
||||
#
|
||||
# Native Language Support
|
||||
#
|
||||
CONFIG_NLS=y
|
||||
CONFIG_NLS_DEFAULT="iso8859-1"
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
# CONFIG_NLS_CODEPAGE_737 is not set
|
||||
# CONFIG_NLS_CODEPAGE_775 is not set
|
||||
# CONFIG_NLS_CODEPAGE_850 is not set
|
||||
# CONFIG_NLS_CODEPAGE_852 is not set
|
||||
# CONFIG_NLS_CODEPAGE_855 is not set
|
||||
# CONFIG_NLS_CODEPAGE_857 is not set
|
||||
# CONFIG_NLS_CODEPAGE_860 is not set
|
||||
# CONFIG_NLS_CODEPAGE_861 is not set
|
||||
# CONFIG_NLS_CODEPAGE_862 is not set
|
||||
# CONFIG_NLS_CODEPAGE_863 is not set
|
||||
# CONFIG_NLS_CODEPAGE_864 is not set
|
||||
# CONFIG_NLS_CODEPAGE_865 is not set
|
||||
# CONFIG_NLS_CODEPAGE_866 is not set
|
||||
# CONFIG_NLS_CODEPAGE_869 is not set
|
||||
# CONFIG_NLS_CODEPAGE_936 is not set
|
||||
# CONFIG_NLS_CODEPAGE_950 is not set
|
||||
# CONFIG_NLS_CODEPAGE_932 is not set
|
||||
# CONFIG_NLS_CODEPAGE_949 is not set
|
||||
# CONFIG_NLS_CODEPAGE_874 is not set
|
||||
# CONFIG_NLS_ISO8859_8 is not set
|
||||
# CONFIG_NLS_CODEPAGE_1250 is not set
|
||||
# CONFIG_NLS_CODEPAGE_1251 is not set
|
||||
CONFIG_NLS_ASCII=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
# CONFIG_NLS_ISO8859_2 is not set
|
||||
# CONFIG_NLS_ISO8859_3 is not set
|
||||
# CONFIG_NLS_ISO8859_4 is not set
|
||||
# CONFIG_NLS_ISO8859_5 is not set
|
||||
# CONFIG_NLS_ISO8859_6 is not set
|
||||
# CONFIG_NLS_ISO8859_7 is not set
|
||||
# CONFIG_NLS_ISO8859_9 is not set
|
||||
# CONFIG_NLS_ISO8859_13 is not set
|
||||
# CONFIG_NLS_ISO8859_14 is not set
|
||||
# CONFIG_NLS_ISO8859_15 is not set
|
||||
# CONFIG_NLS_KOI8_R is not set
|
||||
# CONFIG_NLS_KOI8_U is not set
|
||||
# CONFIG_NLS_UTF8 is not set
|
||||
|
||||
#
|
||||
# iSeries device drivers
|
||||
#
|
||||
CONFIG_VIOCONS=y
|
||||
CONFIG_VIODASD=y
|
||||
CONFIG_VIOCD=m
|
||||
CONFIG_VIOTAPE=m
|
||||
CONFIG_VIOPATH=y
|
||||
|
||||
#
|
||||
# Profiling support
|
||||
#
|
||||
CONFIG_PROFILING=y
|
||||
CONFIG_OPROFILE=y
|
||||
|
||||
#
|
||||
# Kernel hacking
|
||||
#
|
||||
# CONFIG_PRINTK_TIME is not set
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_LOG_BUF_SHIFT=17
|
||||
CONFIG_DETECT_SOFTLOCKUP=y
|
||||
# CONFIG_SCHEDSTATS is not set
|
||||
# CONFIG_DEBUG_SLAB is not set
|
||||
# CONFIG_DEBUG_SPINLOCK is not set
|
||||
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
|
||||
# CONFIG_DEBUG_KOBJECT is not set
|
||||
# CONFIG_DEBUG_INFO is not set
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_DEBUG_STACKOVERFLOW=y
|
||||
# CONFIG_KPROBES is not set
|
||||
CONFIG_DEBUG_STACK_USAGE=y
|
||||
# CONFIG_DEBUGGER is not set
|
||||
# CONFIG_PPCDBG is not set
|
||||
CONFIG_IRQSTACKS=y
|
||||
|
||||
#
|
||||
# Security options
|
||||
#
|
||||
# CONFIG_KEYS is not set
|
||||
# CONFIG_SECURITY is not set
|
||||
|
||||
#
|
||||
# Cryptographic options
|
||||
#
|
||||
CONFIG_CRYPTO=y
|
||||
CONFIG_CRYPTO_HMAC=y
|
||||
CONFIG_CRYPTO_NULL=m
|
||||
CONFIG_CRYPTO_MD4=m
|
||||
CONFIG_CRYPTO_MD5=y
|
||||
CONFIG_CRYPTO_SHA1=m
|
||||
CONFIG_CRYPTO_SHA256=m
|
||||
CONFIG_CRYPTO_SHA512=m
|
||||
CONFIG_CRYPTO_WP512=m
|
||||
CONFIG_CRYPTO_TGR192=m
|
||||
CONFIG_CRYPTO_DES=y
|
||||
CONFIG_CRYPTO_BLOWFISH=m
|
||||
CONFIG_CRYPTO_TWOFISH=m
|
||||
CONFIG_CRYPTO_SERPENT=m
|
||||
CONFIG_CRYPTO_AES=m
|
||||
CONFIG_CRYPTO_CAST5=m
|
||||
CONFIG_CRYPTO_CAST6=m
|
||||
CONFIG_CRYPTO_TEA=m
|
||||
CONFIG_CRYPTO_ARC4=m
|
||||
CONFIG_CRYPTO_KHAZAD=m
|
||||
CONFIG_CRYPTO_ANUBIS=m
|
||||
CONFIG_CRYPTO_DEFLATE=m
|
||||
CONFIG_CRYPTO_MICHAEL_MIC=m
|
||||
CONFIG_CRYPTO_CRC32C=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
|
||||
#
|
||||
# Hardware crypto devices
|
||||
#
|
||||
|
||||
#
|
||||
# Library routines
|
||||
#
|
||||
CONFIG_CRC_CCITT=m
|
||||
# CONFIG_CRC16 is not set
|
||||
CONFIG_CRC32=y
|
||||
CONFIG_LIBCRC32C=m
|
||||
CONFIG_ZLIB_INFLATE=y
|
||||
CONFIG_ZLIB_DEFLATE=m
|
||||
CONFIG_TEXTSEARCH=y
|
||||
CONFIG_TEXTSEARCH_KMP=m
|
||||
CONFIG_TEXTSEARCH_BM=m
|
||||
CONFIG_TEXTSEARCH_FSM=m
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -13,12 +13,15 @@ endif
|
|||
obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
|
||||
signal_32.o pmc.o
|
||||
obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
|
||||
ptrace32.o systbl.o
|
||||
signal_64.o ptrace32.o systbl.o
|
||||
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
|
||||
obj-$(CONFIG_POWER4) += idle_power4.o
|
||||
obj-$(CONFIG_PPC_OF) += of_device.o
|
||||
obj-$(CONFIG_PPC_RTAS) += rtas.o
|
||||
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
|
||||
obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
|
||||
obj-$(CONFIG_IBMVIO) += vio.o
|
||||
obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
|
||||
|
||||
ifeq ($(CONFIG_PPC_MERGE),y)
|
||||
|
||||
|
@ -38,6 +41,7 @@ obj-$(CONFIG_PPC_OF) += prom_init.o
|
|||
obj-$(CONFIG_MODULES) += ppc_ksyms.o
|
||||
obj-$(CONFIG_BOOTX_TEXT) += btext.o
|
||||
obj-$(CONFIG_6xx) += idle_6xx.o
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
|
||||
ifeq ($(CONFIG_PPC_ISERIES),y)
|
||||
$(obj)/head_64.o: $(obj)/lparmap.s
|
||||
|
@ -46,8 +50,9 @@ endif
|
|||
|
||||
else
|
||||
# stuff used from here for ARCH=ppc or ARCH=ppc64
|
||||
smpobj-$(CONFIG_SMP) += smp.o
|
||||
obj-$(CONFIG_PPC64) += traps.o process.o init_task.o time.o \
|
||||
setup-common.o
|
||||
setup-common.o $(smpobj-y)
|
||||
|
||||
|
||||
endif
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#ifdef CONFIG_PPC64
|
||||
#include <asm/paca.h>
|
||||
#include <asm/lppaca.h>
|
||||
#include <asm/iSeries/HvLpEvent.h>
|
||||
#include <asm/iseries/hv_lp_event.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/systemcfg.h>
|
||||
#include <asm/compat.h>
|
||||
|
@ -125,6 +125,9 @@ int main(void)
|
|||
DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
|
||||
DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
|
||||
DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
DEFINE(PACAPGDIR, offsetof(struct paca_struct, pgdir));
|
||||
#endif
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas));
|
||||
DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas));
|
||||
|
|
|
@ -240,7 +240,7 @@ struct cpu_spec cpu_specs[] = {
|
|||
.oprofile_model = &op_model_power4,
|
||||
#endif
|
||||
},
|
||||
{ /* Power5 */
|
||||
{ /* Power5 GR */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x003a0000,
|
||||
.cpu_name = "POWER5 (gr)",
|
||||
|
@ -255,7 +255,7 @@ struct cpu_spec cpu_specs[] = {
|
|||
.oprofile_model = &op_model_power4,
|
||||
#endif
|
||||
},
|
||||
{ /* Power5 */
|
||||
{ /* Power5 GS */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x003b0000,
|
||||
.cpu_name = "POWER5 (gs)",
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include <asm/cputable.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/hvcall.h>
|
||||
#include <asm/iSeries/LparMap.h>
|
||||
#include <asm/iseries/lpar_map.h>
|
||||
#include <asm/thread_info.h>
|
||||
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
|
@ -195,11 +195,11 @@ exception_marker:
|
|||
#define EX_R12 24
|
||||
#define EX_R13 32
|
||||
#define EX_SRR0 40
|
||||
#define EX_R3 40 /* SLB miss saves R3, but not SRR0 */
|
||||
#define EX_DAR 48
|
||||
#define EX_LR 48 /* SLB miss saves LR, but not DAR */
|
||||
#define EX_DSISR 56
|
||||
#define EX_CCR 60
|
||||
#define EX_R3 64
|
||||
#define EX_LR 72
|
||||
|
||||
#define EXCEPTION_PROLOG_PSERIES(area, label) \
|
||||
mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
|
||||
|
@ -419,17 +419,22 @@ data_access_slb_pSeries:
|
|||
mtspr SPRN_SPRG1,r13
|
||||
RUNLATCH_ON(r13)
|
||||
mfspr r13,SPRN_SPRG3 /* get paca address into r13 */
|
||||
std r3,PACA_EXSLB+EX_R3(r13)
|
||||
mfspr r3,SPRN_DAR
|
||||
std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */
|
||||
mfcr r9
|
||||
#ifdef __DISABLED__
|
||||
/* Keep that around for when we re-implement dynamic VSIDs */
|
||||
cmpdi r3,0
|
||||
bge slb_miss_user_pseries
|
||||
#endif /* __DISABLED__ */
|
||||
std r10,PACA_EXSLB+EX_R10(r13)
|
||||
std r11,PACA_EXSLB+EX_R11(r13)
|
||||
std r12,PACA_EXSLB+EX_R12(r13)
|
||||
std r3,PACA_EXSLB+EX_R3(r13)
|
||||
mfspr r9,SPRN_SPRG1
|
||||
std r9,PACA_EXSLB+EX_R13(r13)
|
||||
mfcr r9
|
||||
mfspr r10,SPRN_SPRG1
|
||||
std r10,PACA_EXSLB+EX_R13(r13)
|
||||
mfspr r12,SPRN_SRR1 /* and SRR1 */
|
||||
mfspr r3,SPRN_DAR
|
||||
b .do_slb_miss /* Rel. branch works in real mode */
|
||||
b .slb_miss_realmode /* Rel. branch works in real mode */
|
||||
|
||||
STD_EXCEPTION_PSERIES(0x400, instruction_access)
|
||||
|
||||
|
@ -440,17 +445,22 @@ instruction_access_slb_pSeries:
|
|||
mtspr SPRN_SPRG1,r13
|
||||
RUNLATCH_ON(r13)
|
||||
mfspr r13,SPRN_SPRG3 /* get paca address into r13 */
|
||||
std r3,PACA_EXSLB+EX_R3(r13)
|
||||
mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
|
||||
std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */
|
||||
mfcr r9
|
||||
#ifdef __DISABLED__
|
||||
/* Keep that around for when we re-implement dynamic VSIDs */
|
||||
cmpdi r3,0
|
||||
bge slb_miss_user_pseries
|
||||
#endif /* __DISABLED__ */
|
||||
std r10,PACA_EXSLB+EX_R10(r13)
|
||||
std r11,PACA_EXSLB+EX_R11(r13)
|
||||
std r12,PACA_EXSLB+EX_R12(r13)
|
||||
std r3,PACA_EXSLB+EX_R3(r13)
|
||||
mfspr r9,SPRN_SPRG1
|
||||
std r9,PACA_EXSLB+EX_R13(r13)
|
||||
mfcr r9
|
||||
mfspr r10,SPRN_SPRG1
|
||||
std r10,PACA_EXSLB+EX_R13(r13)
|
||||
mfspr r12,SPRN_SRR1 /* and SRR1 */
|
||||
mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
|
||||
b .do_slb_miss /* Rel. branch works in real mode */
|
||||
b .slb_miss_realmode /* Rel. branch works in real mode */
|
||||
|
||||
STD_EXCEPTION_PSERIES(0x500, hardware_interrupt)
|
||||
STD_EXCEPTION_PSERIES(0x600, alignment)
|
||||
|
@ -508,6 +518,38 @@ _GLOBAL(do_stab_bolted_pSeries)
|
|||
mfspr r12,SPRN_SPRG2
|
||||
EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)
|
||||
|
||||
/*
|
||||
* We have some room here we use that to put
|
||||
* the peries slb miss user trampoline code so it's reasonably
|
||||
* away from slb_miss_user_common to avoid problems with rfid
|
||||
*
|
||||
* This is used for when the SLB miss handler has to go virtual,
|
||||
* which doesn't happen for now anymore but will once we re-implement
|
||||
* dynamic VSIDs for shared page tables
|
||||
*/
|
||||
#ifdef __DISABLED__
|
||||
slb_miss_user_pseries:
|
||||
std r10,PACA_EXGEN+EX_R10(r13)
|
||||
std r11,PACA_EXGEN+EX_R11(r13)
|
||||
std r12,PACA_EXGEN+EX_R12(r13)
|
||||
mfspr r10,SPRG1
|
||||
ld r11,PACA_EXSLB+EX_R9(r13)
|
||||
ld r12,PACA_EXSLB+EX_R3(r13)
|
||||
std r10,PACA_EXGEN+EX_R13(r13)
|
||||
std r11,PACA_EXGEN+EX_R9(r13)
|
||||
std r12,PACA_EXGEN+EX_R3(r13)
|
||||
clrrdi r12,r13,32
|
||||
mfmsr r10
|
||||
mfspr r11,SRR0 /* save SRR0 */
|
||||
ori r12,r12,slb_miss_user_common@l /* virt addr of handler */
|
||||
ori r10,r10,MSR_IR|MSR_DR|MSR_RI
|
||||
mtspr SRR0,r12
|
||||
mfspr r12,SRR1 /* and SRR1 */
|
||||
mtspr SRR1,r10
|
||||
rfid
|
||||
b . /* prevent spec. execution */
|
||||
#endif /* __DISABLED__ */
|
||||
|
||||
/*
|
||||
* Vectors for the FWNMI option. Share common code.
|
||||
*/
|
||||
|
@ -559,22 +601,59 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
|
|||
.globl data_access_slb_iSeries
|
||||
data_access_slb_iSeries:
|
||||
mtspr SPRN_SPRG1,r13 /* save r13 */
|
||||
EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
|
||||
mfspr r13,SPRN_SPRG3 /* get paca address into r13 */
|
||||
std r3,PACA_EXSLB+EX_R3(r13)
|
||||
ld r12,PACALPPACA+LPPACASRR1(r13)
|
||||
mfspr r3,SPRN_DAR
|
||||
b .do_slb_miss
|
||||
std r9,PACA_EXSLB+EX_R9(r13)
|
||||
mfcr r9
|
||||
#ifdef __DISABLED__
|
||||
cmpdi r3,0
|
||||
bge slb_miss_user_iseries
|
||||
#endif
|
||||
std r10,PACA_EXSLB+EX_R10(r13)
|
||||
std r11,PACA_EXSLB+EX_R11(r13)
|
||||
std r12,PACA_EXSLB+EX_R12(r13)
|
||||
mfspr r10,SPRN_SPRG1
|
||||
std r10,PACA_EXSLB+EX_R13(r13)
|
||||
ld r12,PACALPPACA+LPPACASRR1(r13);
|
||||
b .slb_miss_realmode
|
||||
|
||||
STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN)
|
||||
|
||||
.globl instruction_access_slb_iSeries
|
||||
instruction_access_slb_iSeries:
|
||||
mtspr SPRN_SPRG1,r13 /* save r13 */
|
||||
EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
|
||||
mfspr r13,SPRN_SPRG3 /* get paca address into r13 */
|
||||
std r3,PACA_EXSLB+EX_R3(r13)
|
||||
ld r12,PACALPPACA+LPPACASRR1(r13)
|
||||
ld r3,PACALPPACA+LPPACASRR0(r13)
|
||||
b .do_slb_miss
|
||||
ld r3,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */
|
||||
std r9,PACA_EXSLB+EX_R9(r13)
|
||||
mfcr r9
|
||||
#ifdef __DISABLED__
|
||||
cmpdi r3,0
|
||||
bge .slb_miss_user_iseries
|
||||
#endif
|
||||
std r10,PACA_EXSLB+EX_R10(r13)
|
||||
std r11,PACA_EXSLB+EX_R11(r13)
|
||||
std r12,PACA_EXSLB+EX_R12(r13)
|
||||
mfspr r10,SPRN_SPRG1
|
||||
std r10,PACA_EXSLB+EX_R13(r13)
|
||||
ld r12,PACALPPACA+LPPACASRR1(r13);
|
||||
b .slb_miss_realmode
|
||||
|
||||
#ifdef __DISABLED__
|
||||
slb_miss_user_iseries:
|
||||
std r10,PACA_EXGEN+EX_R10(r13)
|
||||
std r11,PACA_EXGEN+EX_R11(r13)
|
||||
std r12,PACA_EXGEN+EX_R12(r13)
|
||||
mfspr r10,SPRG1
|
||||
ld r11,PACA_EXSLB+EX_R9(r13)
|
||||
ld r12,PACA_EXSLB+EX_R3(r13)
|
||||
std r10,PACA_EXGEN+EX_R13(r13)
|
||||
std r11,PACA_EXGEN+EX_R9(r13)
|
||||
std r12,PACA_EXGEN+EX_R3(r13)
|
||||
EXCEPTION_PROLOG_ISERIES_2
|
||||
b slb_miss_user_common
|
||||
#endif
|
||||
|
||||
MASKABLE_EXCEPTION_ISERIES(0x500, hardware_interrupt)
|
||||
STD_EXCEPTION_ISERIES(0x600, alignment, PACA_EXGEN)
|
||||
|
@ -809,6 +888,126 @@ instruction_access_common:
|
|||
li r5,0x400
|
||||
b .do_hash_page /* Try to handle as hpte fault */
|
||||
|
||||
/*
|
||||
* Here is the common SLB miss user that is used when going to virtual
|
||||
* mode for SLB misses, that is currently not used
|
||||
*/
|
||||
#ifdef __DISABLED__
|
||||
.align 7
|
||||
.globl slb_miss_user_common
|
||||
slb_miss_user_common:
|
||||
mflr r10
|
||||
std r3,PACA_EXGEN+EX_DAR(r13)
|
||||
stw r9,PACA_EXGEN+EX_CCR(r13)
|
||||
std r10,PACA_EXGEN+EX_LR(r13)
|
||||
std r11,PACA_EXGEN+EX_SRR0(r13)
|
||||
bl .slb_allocate_user
|
||||
|
||||
ld r10,PACA_EXGEN+EX_LR(r13)
|
||||
ld r3,PACA_EXGEN+EX_R3(r13)
|
||||
lwz r9,PACA_EXGEN+EX_CCR(r13)
|
||||
ld r11,PACA_EXGEN+EX_SRR0(r13)
|
||||
mtlr r10
|
||||
beq- slb_miss_fault
|
||||
|
||||
andi. r10,r12,MSR_RI /* check for unrecoverable exception */
|
||||
beq- unrecov_user_slb
|
||||
mfmsr r10
|
||||
|
||||
.machine push
|
||||
.machine "power4"
|
||||
mtcrf 0x80,r9
|
||||
.machine pop
|
||||
|
||||
clrrdi r10,r10,2 /* clear RI before setting SRR0/1 */
|
||||
mtmsrd r10,1
|
||||
|
||||
mtspr SRR0,r11
|
||||
mtspr SRR1,r12
|
||||
|
||||
ld r9,PACA_EXGEN+EX_R9(r13)
|
||||
ld r10,PACA_EXGEN+EX_R10(r13)
|
||||
ld r11,PACA_EXGEN+EX_R11(r13)
|
||||
ld r12,PACA_EXGEN+EX_R12(r13)
|
||||
ld r13,PACA_EXGEN+EX_R13(r13)
|
||||
rfid
|
||||
b .
|
||||
|
||||
slb_miss_fault:
|
||||
EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN)
|
||||
ld r4,PACA_EXGEN+EX_DAR(r13)
|
||||
li r5,0
|
||||
std r4,_DAR(r1)
|
||||
std r5,_DSISR(r1)
|
||||
b .handle_page_fault
|
||||
|
||||
unrecov_user_slb:
|
||||
EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN)
|
||||
DISABLE_INTS
|
||||
bl .save_nvgprs
|
||||
1: addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .unrecoverable_exception
|
||||
b 1b
|
||||
|
||||
#endif /* __DISABLED__ */
|
||||
|
||||
|
||||
/*
|
||||
* r13 points to the PACA, r9 contains the saved CR,
|
||||
* r12 contain the saved SRR1, SRR0 is still ready for return
|
||||
* r3 has the faulting address
|
||||
* r9 - r13 are saved in paca->exslb.
|
||||
* r3 is saved in paca->slb_r3
|
||||
* We assume we aren't going to take any exceptions during this procedure.
|
||||
*/
|
||||
_GLOBAL(slb_miss_realmode)
|
||||
mflr r10
|
||||
|
||||
stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
|
||||
std r10,PACA_EXSLB+EX_LR(r13) /* save LR */
|
||||
|
||||
bl .slb_allocate_realmode
|
||||
|
||||
/* All done -- return from exception. */
|
||||
|
||||
ld r10,PACA_EXSLB+EX_LR(r13)
|
||||
ld r3,PACA_EXSLB+EX_R3(r13)
|
||||
lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */
|
||||
#endif /* CONFIG_PPC_ISERIES */
|
||||
|
||||
mtlr r10
|
||||
|
||||
andi. r10,r12,MSR_RI /* check for unrecoverable exception */
|
||||
beq- unrecov_slb
|
||||
|
||||
.machine push
|
||||
.machine "power4"
|
||||
mtcrf 0x80,r9
|
||||
mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
|
||||
.machine pop
|
||||
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
mtspr SPRN_SRR0,r11
|
||||
mtspr SPRN_SRR1,r12
|
||||
#endif /* CONFIG_PPC_ISERIES */
|
||||
ld r9,PACA_EXSLB+EX_R9(r13)
|
||||
ld r10,PACA_EXSLB+EX_R10(r13)
|
||||
ld r11,PACA_EXSLB+EX_R11(r13)
|
||||
ld r12,PACA_EXSLB+EX_R12(r13)
|
||||
ld r13,PACA_EXSLB+EX_R13(r13)
|
||||
rfid
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
unrecov_slb:
|
||||
EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
|
||||
DISABLE_INTS
|
||||
bl .save_nvgprs
|
||||
1: addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .unrecoverable_exception
|
||||
b 1b
|
||||
|
||||
.align 7
|
||||
.globl hardware_interrupt_common
|
||||
.globl hardware_interrupt_entry
|
||||
|
@ -1138,62 +1337,6 @@ _GLOBAL(do_stab_bolted)
|
|||
rfid
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
/*
|
||||
* r13 points to the PACA, r9 contains the saved CR,
|
||||
* r11 and r12 contain the saved SRR0 and SRR1.
|
||||
* r3 has the faulting address
|
||||
* r9 - r13 are saved in paca->exslb.
|
||||
* r3 is saved in paca->slb_r3
|
||||
* We assume we aren't going to take any exceptions during this procedure.
|
||||
*/
|
||||
_GLOBAL(do_slb_miss)
|
||||
mflr r10
|
||||
|
||||
stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
|
||||
std r10,PACA_EXSLB+EX_LR(r13) /* save LR */
|
||||
|
||||
bl .slb_allocate /* handle it */
|
||||
|
||||
/* All done -- return from exception. */
|
||||
|
||||
ld r10,PACA_EXSLB+EX_LR(r13)
|
||||
ld r3,PACA_EXSLB+EX_R3(r13)
|
||||
lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */
|
||||
#endif /* CONFIG_PPC_ISERIES */
|
||||
|
||||
mtlr r10
|
||||
|
||||
andi. r10,r12,MSR_RI /* check for unrecoverable exception */
|
||||
beq- unrecov_slb
|
||||
|
||||
.machine push
|
||||
.machine "power4"
|
||||
mtcrf 0x80,r9
|
||||
mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
|
||||
.machine pop
|
||||
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
mtspr SPRN_SRR0,r11
|
||||
mtspr SPRN_SRR1,r12
|
||||
#endif /* CONFIG_PPC_ISERIES */
|
||||
ld r9,PACA_EXSLB+EX_R9(r13)
|
||||
ld r10,PACA_EXSLB+EX_R10(r13)
|
||||
ld r11,PACA_EXSLB+EX_R11(r13)
|
||||
ld r12,PACA_EXSLB+EX_R12(r13)
|
||||
ld r13,PACA_EXSLB+EX_R13(r13)
|
||||
rfid
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
unrecov_slb:
|
||||
EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
|
||||
DISABLE_INTS
|
||||
bl .save_nvgprs
|
||||
1: addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .unrecoverable_exception
|
||||
b 1b
|
||||
|
||||
/*
|
||||
* Space for CPU0's segment table.
|
||||
*
|
||||
|
@ -1569,7 +1712,10 @@ _GLOBAL(__secondary_start)
|
|||
#endif
|
||||
/* Initialize the first segment table (or SLB) entry */
|
||||
ld r3,PACASTABVIRT(r13) /* get addr of segment table */
|
||||
BEGIN_FTR_SECTION
|
||||
bl .stab_initialize
|
||||
END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
|
||||
bl .slb_initialize
|
||||
|
||||
/* Initialize the kernel stack. Just a repeat for iSeries. */
|
||||
LOADADDR(r3,current_set)
|
||||
|
@ -1914,24 +2060,6 @@ _GLOBAL(hmt_start_secondary)
|
|||
blr
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_KEXEC) || defined(CONFIG_SMP)
|
||||
_GLOBAL(smp_release_cpus)
|
||||
/* All secondary cpus are 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.
|
||||
* XXX This does nothing useful on iSeries, secondaries are
|
||||
* already waiting on their paca.
|
||||
*/
|
||||
li r3,1
|
||||
LOADADDR(r5,__secondary_hold_spinloop)
|
||||
std r3,0(r5)
|
||||
sync
|
||||
blr
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
|
||||
/*
|
||||
* We put a few things here that have to be page-aligned.
|
||||
* This stuff goes at the beginning of the bss, which is page-aligned.
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/iSeries/LparMap.h>
|
||||
#include <asm/iseries/lpar_map.h>
|
||||
|
||||
const struct LparMap __attribute__((__section__(".text"))) xLparMap = {
|
||||
.xNumberEsids = HvEsidsToMap,
|
||||
|
@ -25,7 +25,7 @@ const struct LparMap __attribute__((__section__(".text"))) xLparMap = {
|
|||
.xRanges = {
|
||||
{ .xPages = HvPagesToMap,
|
||||
.xOffset = 0,
|
||||
.xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - PAGE_SHIFT),
|
||||
.xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - HW_PAGE_SHIFT),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -91,6 +91,22 @@ typedef struct sigaltstack_32 {
|
|||
compat_size_t ss_size;
|
||||
} stack_32_t;
|
||||
|
||||
struct pt_regs32 {
|
||||
unsigned int gpr[32];
|
||||
unsigned int nip;
|
||||
unsigned int msr;
|
||||
unsigned int orig_gpr3; /* Used for restarting system calls */
|
||||
unsigned int ctr;
|
||||
unsigned int link;
|
||||
unsigned int xer;
|
||||
unsigned int ccr;
|
||||
unsigned int mq; /* 601 only (not used at present) */
|
||||
unsigned int trap; /* Reason for being here */
|
||||
unsigned int dar; /* Fault registers */
|
||||
unsigned int dsisr;
|
||||
unsigned int result; /* Result of a system call */
|
||||
};
|
||||
|
||||
struct sigcontext32 {
|
||||
unsigned int _unused[4];
|
||||
int signal;
|
|
@ -81,15 +81,6 @@ EXPORT_SYMBOL(_prep_type);
|
|||
EXPORT_SYMBOL(ucSystemType);
|
||||
#endif
|
||||
|
||||
#if !defined(__INLINE_BITOPS)
|
||||
EXPORT_SYMBOL(set_bit);
|
||||
EXPORT_SYMBOL(clear_bit);
|
||||
EXPORT_SYMBOL(change_bit);
|
||||
EXPORT_SYMBOL(test_and_set_bit);
|
||||
EXPORT_SYMBOL(test_and_clear_bit);
|
||||
EXPORT_SYMBOL(test_and_change_bit);
|
||||
#endif /* __INLINE_BITOPS */
|
||||
|
||||
EXPORT_SYMBOL(strcpy);
|
||||
EXPORT_SYMBOL(strncpy);
|
||||
EXPORT_SYMBOL(strcat);
|
||||
|
|
|
@ -48,8 +48,8 @@
|
|||
#include <asm/prom.h>
|
||||
#ifdef CONFIG_PPC64
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/plpar_wrappers.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/machdep.h>
|
||||
#endif
|
||||
|
||||
extern unsigned long _get_SP(void);
|
||||
|
@ -201,27 +201,15 @@ int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs)
|
|||
}
|
||||
#endif /* CONFIG_SPE */
|
||||
|
||||
static void set_dabr_spr(unsigned long val)
|
||||
{
|
||||
mtspr(SPRN_DABR, val);
|
||||
}
|
||||
|
||||
int set_dabr(unsigned long dabr)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
if (firmware_has_feature(FW_FEATURE_XDABR)) {
|
||||
/* We want to catch accesses from kernel and userspace */
|
||||
unsigned long flags = H_DABRX_KERNEL|H_DABRX_USER;
|
||||
ret = plpar_set_xdabr(dabr, flags);
|
||||
} else if (firmware_has_feature(FW_FEATURE_DABR)) {
|
||||
ret = plpar_set_dabr(dabr);
|
||||
} else
|
||||
if (ppc_md.set_dabr)
|
||||
return ppc_md.set_dabr(dabr);
|
||||
#endif
|
||||
set_dabr_spr(dabr);
|
||||
|
||||
return ret;
|
||||
mtspr(SPRN_DABR, dabr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
|
@ -566,12 +554,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
|
|||
#ifdef CONFIG_PPC64
|
||||
if (cpu_has_feature(CPU_FTR_SLB)) {
|
||||
unsigned long sp_vsid = get_kernel_vsid(sp);
|
||||
unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp;
|
||||
|
||||
sp_vsid <<= SLB_VSID_SHIFT;
|
||||
sp_vsid |= SLB_VSID_KERNEL;
|
||||
if (cpu_has_feature(CPU_FTR_16M_PAGE))
|
||||
sp_vsid |= SLB_VSID_L;
|
||||
|
||||
sp_vsid |= SLB_VSID_KERNEL | llp;
|
||||
p->thread.ksp_vsid = sp_vsid;
|
||||
}
|
||||
|
||||
|
|
|
@ -724,10 +724,10 @@ static inline char *find_flat_dt_string(u32 offset)
|
|||
* used to extract the memory informations at boot before we can
|
||||
* unflatten the tree
|
||||
*/
|
||||
static int __init scan_flat_dt(int (*it)(unsigned long node,
|
||||
const char *uname, int depth,
|
||||
void *data),
|
||||
void *data)
|
||||
int __init of_scan_flat_dt(int (*it)(unsigned long node,
|
||||
const char *uname, int depth,
|
||||
void *data),
|
||||
void *data)
|
||||
{
|
||||
unsigned long p = ((unsigned long)initial_boot_params) +
|
||||
initial_boot_params->off_dt_struct;
|
||||
|
@ -784,8 +784,8 @@ static int __init scan_flat_dt(int (*it)(unsigned long node,
|
|||
* This function can be used within scan_flattened_dt callback to get
|
||||
* access to properties
|
||||
*/
|
||||
static void* __init get_flat_dt_prop(unsigned long node, const char *name,
|
||||
unsigned long *size)
|
||||
void* __init of_get_flat_dt_prop(unsigned long node, const char *name,
|
||||
unsigned long *size)
|
||||
{
|
||||
unsigned long p = node;
|
||||
|
||||
|
@ -1087,7 +1087,7 @@ void __init unflatten_device_tree(void)
|
|||
static int __init early_init_dt_scan_cpus(unsigned long node,
|
||||
const char *uname, int depth, void *data)
|
||||
{
|
||||
char *type = get_flat_dt_prop(node, "device_type", NULL);
|
||||
char *type = of_get_flat_dt_prop(node, "device_type", NULL);
|
||||
u32 *prop;
|
||||
unsigned long size = 0;
|
||||
|
||||
|
@ -1095,19 +1095,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
|
|||
if (type == NULL || strcmp(type, "cpu") != 0)
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
/* On LPAR, look for the first ibm,pft-size property for the hash table size
|
||||
*/
|
||||
if (systemcfg->platform == PLATFORM_PSERIES_LPAR && ppc64_pft_size == 0) {
|
||||
u32 *pft_size;
|
||||
pft_size = get_flat_dt_prop(node, "ibm,pft-size", NULL);
|
||||
if (pft_size != NULL) {
|
||||
/* pft_size[0] is the NUMA CEC cookie */
|
||||
ppc64_pft_size = pft_size[1];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
boot_cpuid = 0;
|
||||
boot_cpuid_phys = 0;
|
||||
if (initial_boot_params && initial_boot_params->version >= 2) {
|
||||
|
@ -1117,8 +1104,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
|
|||
boot_cpuid_phys = initial_boot_params->boot_cpuid_phys;
|
||||
} else {
|
||||
/* Check if it's the boot-cpu, set it's hw index now */
|
||||
if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) {
|
||||
prop = get_flat_dt_prop(node, "reg", NULL);
|
||||
if (of_get_flat_dt_prop(node,
|
||||
"linux,boot-cpu", NULL) != NULL) {
|
||||
prop = of_get_flat_dt_prop(node, "reg", NULL);
|
||||
if (prop != NULL)
|
||||
boot_cpuid_phys = *prop;
|
||||
}
|
||||
|
@ -1127,14 +1115,14 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
|
|||
|
||||
#ifdef CONFIG_ALTIVEC
|
||||
/* Check if we have a VMX and eventually update CPU features */
|
||||
prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", &size);
|
||||
prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", &size);
|
||||
if (prop && (*prop) > 0) {
|
||||
cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
|
||||
cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
|
||||
}
|
||||
|
||||
/* Same goes for Apple's "altivec" property */
|
||||
prop = (u32 *)get_flat_dt_prop(node, "altivec", NULL);
|
||||
prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL);
|
||||
if (prop) {
|
||||
cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
|
||||
cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
|
||||
|
@ -1147,7 +1135,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
|
|||
* this by looking at the size of the ibm,ppc-interrupt-server#s
|
||||
* property
|
||||
*/
|
||||
prop = (u32 *)get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
|
||||
prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
|
||||
&size);
|
||||
cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
|
||||
if (prop && ((size / sizeof(u32)) > 1))
|
||||
|
@ -1170,7 +1158,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
|
|||
return 0;
|
||||
|
||||
/* get platform type */
|
||||
prop = (u32 *)get_flat_dt_prop(node, "linux,platform", NULL);
|
||||
prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL);
|
||||
if (prop == NULL)
|
||||
return 0;
|
||||
#ifdef CONFIG_PPC64
|
||||
|
@ -1183,21 +1171,21 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
|
|||
|
||||
#ifdef CONFIG_PPC64
|
||||
/* check if iommu is forced on or off */
|
||||
if (get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
|
||||
if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
|
||||
iommu_is_off = 1;
|
||||
if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL)
|
||||
if (of_get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL)
|
||||
iommu_force_on = 1;
|
||||
#endif
|
||||
|
||||
lprop = get_flat_dt_prop(node, "linux,memory-limit", NULL);
|
||||
lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
|
||||
if (lprop)
|
||||
memory_limit = *lprop;
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
lprop = get_flat_dt_prop(node, "linux,tce-alloc-start", NULL);
|
||||
lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL);
|
||||
if (lprop)
|
||||
tce_alloc_start = *lprop;
|
||||
lprop = get_flat_dt_prop(node, "linux,tce-alloc-end", NULL);
|
||||
lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL);
|
||||
if (lprop)
|
||||
tce_alloc_end = *lprop;
|
||||
#endif
|
||||
|
@ -1209,9 +1197,9 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
|
|||
{
|
||||
u64 *basep, *entryp;
|
||||
|
||||
basep = get_flat_dt_prop(node, "linux,rtas-base", NULL);
|
||||
entryp = get_flat_dt_prop(node, "linux,rtas-entry", NULL);
|
||||
prop = get_flat_dt_prop(node, "linux,rtas-size", NULL);
|
||||
basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL);
|
||||
entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
|
||||
prop = of_get_flat_dt_prop(node, "linux,rtas-size", NULL);
|
||||
if (basep && entryp && prop) {
|
||||
rtas.base = *basep;
|
||||
rtas.entry = *entryp;
|
||||
|
@ -1232,11 +1220,11 @@ static int __init early_init_dt_scan_root(unsigned long node,
|
|||
if (depth != 0)
|
||||
return 0;
|
||||
|
||||
prop = get_flat_dt_prop(node, "#size-cells", NULL);
|
||||
prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
|
||||
dt_root_size_cells = (prop == NULL) ? 1 : *prop;
|
||||
DBG("dt_root_size_cells = %x\n", dt_root_size_cells);
|
||||
|
||||
prop = get_flat_dt_prop(node, "#address-cells", NULL);
|
||||
prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
|
||||
dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
|
||||
DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells);
|
||||
|
||||
|
@ -1271,7 +1259,7 @@ static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp)
|
|||
static int __init early_init_dt_scan_memory(unsigned long node,
|
||||
const char *uname, int depth, void *data)
|
||||
{
|
||||
char *type = get_flat_dt_prop(node, "device_type", NULL);
|
||||
char *type = of_get_flat_dt_prop(node, "device_type", NULL);
|
||||
cell_t *reg, *endp;
|
||||
unsigned long l;
|
||||
|
||||
|
@ -1279,13 +1267,13 @@ static int __init early_init_dt_scan_memory(unsigned long node,
|
|||
if (type == NULL || strcmp(type, "memory") != 0)
|
||||
return 0;
|
||||
|
||||
reg = (cell_t *)get_flat_dt_prop(node, "reg", &l);
|
||||
reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);
|
||||
if (reg == NULL)
|
||||
return 0;
|
||||
|
||||
endp = reg + (l / sizeof(cell_t));
|
||||
|
||||
DBG("memory scan node %s ..., reg size %ld, data: %x %x %x %x, ...\n",
|
||||
DBG("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",
|
||||
uname, l, reg[0], reg[1], reg[2], reg[3]);
|
||||
|
||||
while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
|
||||
|
@ -1343,12 +1331,12 @@ void __init early_init_devtree(void *params)
|
|||
* device-tree, including the platform type, initrd location and
|
||||
* size, TCE reserve, and more ...
|
||||
*/
|
||||
scan_flat_dt(early_init_dt_scan_chosen, NULL);
|
||||
of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
|
||||
|
||||
/* Scan memory nodes and rebuild LMBs */
|
||||
lmb_init();
|
||||
scan_flat_dt(early_init_dt_scan_root, NULL);
|
||||
scan_flat_dt(early_init_dt_scan_memory, NULL);
|
||||
of_scan_flat_dt(early_init_dt_scan_root, NULL);
|
||||
of_scan_flat_dt(early_init_dt_scan_memory, NULL);
|
||||
lmb_enforce_memory_limit(memory_limit);
|
||||
lmb_analyze();
|
||||
#ifdef CONFIG_PPC64
|
||||
|
@ -1363,10 +1351,10 @@ void __init early_init_devtree(void *params)
|
|||
|
||||
DBG("Scanning CPUs ...\n");
|
||||
|
||||
/* Retreive hash table size from flattened tree plus other
|
||||
* CPU related informations (altivec support, boot CPU ID, ...)
|
||||
/* Retreive CPU related informations from the flat tree
|
||||
* (altivec support, boot CPU ID, ...)
|
||||
*/
|
||||
scan_flat_dt(early_init_dt_scan_cpus, NULL);
|
||||
of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
|
||||
|
||||
DBG(" <- early_init_devtree()\n");
|
||||
}
|
||||
|
|
|
@ -2000,7 +2000,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
|
|||
#endif
|
||||
|
||||
/*
|
||||
* On pSeries and BPA, copy the CPU hold code
|
||||
* Copy the CPU hold code
|
||||
*/
|
||||
if (RELOC(of_platform) != PLATFORM_POWERMAC)
|
||||
copy_and_flush(0, KERNELBASE + offset, 0x100, 0);
|
||||
|
|
|
@ -42,6 +42,13 @@ DEFINE_SPINLOCK(rtas_data_buf_lock);
|
|||
char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned;
|
||||
unsigned long rtas_rmo_buf;
|
||||
|
||||
/*
|
||||
* If non-NULL, this gets called when the kernel terminates.
|
||||
* This is done like this so rtas_flash can be a module.
|
||||
*/
|
||||
void (*rtas_flash_term_hook)(int);
|
||||
EXPORT_SYMBOL(rtas_flash_term_hook);
|
||||
|
||||
/*
|
||||
* call_rtas_display_status and call_rtas_display_status_delay
|
||||
* are designed only for very early low-level debugging, which
|
||||
|
@ -206,6 +213,7 @@ void rtas_progress(char *s, unsigned short hex)
|
|||
|
||||
spin_unlock(&progress_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(rtas_progress); /* needed by rtas_flash module */
|
||||
|
||||
int rtas_token(const char *service)
|
||||
{
|
||||
|
@ -492,6 +500,8 @@ int rtas_set_indicator(int indicator, int index, int new_value)
|
|||
|
||||
void rtas_restart(char *cmd)
|
||||
{
|
||||
if (rtas_flash_term_hook)
|
||||
rtas_flash_term_hook(SYS_RESTART);
|
||||
printk("RTAS system-reboot returned %d\n",
|
||||
rtas_call(rtas_token("system-reboot"), 0, 1, NULL));
|
||||
for (;;);
|
||||
|
@ -499,6 +509,8 @@ void rtas_restart(char *cmd)
|
|||
|
||||
void rtas_power_off(void)
|
||||
{
|
||||
if (rtas_flash_term_hook)
|
||||
rtas_flash_term_hook(SYS_POWER_OFF);
|
||||
/* allow power on only with power button press */
|
||||
printk("RTAS power-off returned %d\n",
|
||||
rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1));
|
||||
|
@ -507,7 +519,12 @@ void rtas_power_off(void)
|
|||
|
||||
void rtas_halt(void)
|
||||
{
|
||||
rtas_power_off();
|
||||
if (rtas_flash_term_hook)
|
||||
rtas_flash_term_hook(SYS_HALT);
|
||||
/* allow power on only with power button press */
|
||||
printk("RTAS power-off returned %d\n",
|
||||
rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1));
|
||||
for (;;);
|
||||
}
|
||||
|
||||
/* Must be in the RMO region, so we place it here */
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <asm/delay.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/rtas.h>
|
||||
#include <asm/abs_addr.h>
|
||||
|
||||
#define MODULE_VERS "1.0"
|
||||
#define MODULE_NAME "rtas_flash"
|
||||
|
@ -71,10 +72,36 @@
|
|||
#define VALIDATE_BUF_SIZE 4096
|
||||
#define RTAS_MSG_MAXLEN 64
|
||||
|
||||
struct flash_block {
|
||||
char *data;
|
||||
unsigned long length;
|
||||
};
|
||||
|
||||
/* This struct is very similar but not identical to
|
||||
* that needed by the rtas flash update.
|
||||
* All we need to do for rtas is rewrite num_blocks
|
||||
* into a version/length and translate the pointers
|
||||
* to absolute.
|
||||
*/
|
||||
#define FLASH_BLOCKS_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct flash_block))
|
||||
struct flash_block_list {
|
||||
unsigned long num_blocks;
|
||||
struct flash_block_list *next;
|
||||
struct flash_block blocks[FLASH_BLOCKS_PER_NODE];
|
||||
};
|
||||
struct flash_block_list_header { /* just the header of flash_block_list */
|
||||
unsigned long num_blocks;
|
||||
struct flash_block_list *next;
|
||||
};
|
||||
|
||||
static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL};
|
||||
|
||||
#define FLASH_BLOCK_LIST_VERSION (1UL)
|
||||
|
||||
/* Local copy of the flash block list.
|
||||
* We only allow one open of the flash proc file and create this
|
||||
* list as we go. This list will be put in the kernel's
|
||||
* rtas_firmware_flash_list global var once it is fully read.
|
||||
* list as we go. This list will be put in the
|
||||
* rtas_firmware_flash_list var once it is fully read.
|
||||
*
|
||||
* For convenience as we build the list we use virtual addrs,
|
||||
* we do not fill in the version number, and the length field
|
||||
|
@ -562,6 +589,86 @@ static int validate_flash_release(struct inode *inode, struct file *file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void rtas_flash_firmware(int reboot_type)
|
||||
{
|
||||
unsigned long image_size;
|
||||
struct flash_block_list *f, *next, *flist;
|
||||
unsigned long rtas_block_list;
|
||||
int i, status, update_token;
|
||||
|
||||
if (rtas_firmware_flash_list.next == NULL)
|
||||
return; /* nothing to do */
|
||||
|
||||
if (reboot_type != SYS_RESTART) {
|
||||
printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n");
|
||||
printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
update_token = rtas_token("ibm,update-flash-64-and-reboot");
|
||||
if (update_token == RTAS_UNKNOWN_SERVICE) {
|
||||
printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot "
|
||||
"is not available -- not a service partition?\n");
|
||||
printk(KERN_ALERT "FLASH: firmware will not be flashed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* NOTE: the "first" block list is a global var with no data
|
||||
* blocks in the kernel data segment. We do this because
|
||||
* we want to ensure this block_list addr is under 4GB.
|
||||
*/
|
||||
rtas_firmware_flash_list.num_blocks = 0;
|
||||
flist = (struct flash_block_list *)&rtas_firmware_flash_list;
|
||||
rtas_block_list = virt_to_abs(flist);
|
||||
if (rtas_block_list >= 4UL*1024*1024*1024) {
|
||||
printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n");
|
||||
/* Update the block_list in place. */
|
||||
image_size = 0;
|
||||
for (f = flist; f; f = next) {
|
||||
/* Translate data addrs to absolute */
|
||||
for (i = 0; i < f->num_blocks; i++) {
|
||||
f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data);
|
||||
image_size += f->blocks[i].length;
|
||||
}
|
||||
next = f->next;
|
||||
/* Don't translate NULL pointer for last entry */
|
||||
if (f->next)
|
||||
f->next = (struct flash_block_list *)virt_to_abs(f->next);
|
||||
else
|
||||
f->next = NULL;
|
||||
/* make num_blocks into the version/length field */
|
||||
f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16);
|
||||
}
|
||||
|
||||
printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size);
|
||||
printk(KERN_ALERT "FLASH: performing flash and reboot\n");
|
||||
rtas_progress("Flashing \n", 0x0);
|
||||
rtas_progress("Please Wait... ", 0x0);
|
||||
printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n");
|
||||
status = rtas_call(update_token, 1, 1, NULL, rtas_block_list);
|
||||
switch (status) { /* should only get "bad" status */
|
||||
case 0:
|
||||
printk(KERN_ALERT "FLASH: success\n");
|
||||
break;
|
||||
case -1:
|
||||
printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n");
|
||||
break;
|
||||
case -3:
|
||||
printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n");
|
||||
break;
|
||||
case -4:
|
||||
printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n");
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_flash_pde(struct proc_dir_entry *dp)
|
||||
{
|
||||
if (dp) {
|
||||
|
@ -701,6 +808,7 @@ int __init rtas_flash_init(void)
|
|||
if (rc != 0)
|
||||
goto cleanup;
|
||||
|
||||
rtas_flash_term_hook = rtas_flash_firmware;
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
|
@ -714,6 +822,7 @@ cleanup:
|
|||
|
||||
void __exit rtas_flash_cleanup(void)
|
||||
{
|
||||
rtas_flash_term_hook = NULL;
|
||||
remove_flash_pde(firmware_flash_pde);
|
||||
remove_flash_pde(firmware_update_pde);
|
||||
remove_flash_pde(validate_pde);
|
|
@ -170,11 +170,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#ifdef CONFIG_PPC64 /* XXX for now */
|
||||
pvr = per_cpu(pvr, cpu_id);
|
||||
#else
|
||||
pvr = cpu_data[cpu_id].pvr;
|
||||
#endif
|
||||
#else
|
||||
pvr = mfspr(SPRN_PVR);
|
||||
#endif
|
||||
|
@ -201,11 +197,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||
#ifdef CONFIG_TAU_AVERAGE
|
||||
/* more straightforward, but potentially misleading */
|
||||
seq_printf(m, "temperature \t: %u C (uncalibrated)\n",
|
||||
cpu_temp(i));
|
||||
cpu_temp(cpu_id));
|
||||
#else
|
||||
/* show the actual temp sensor range */
|
||||
u32 temp;
|
||||
temp = cpu_temp_both(i);
|
||||
temp = cpu_temp_both(cpu_id);
|
||||
seq_printf(m, "temperature \t: %u-%u C (uncalibrated)\n",
|
||||
temp & 0xff, temp >> 16);
|
||||
#endif
|
||||
|
@ -408,3 +404,118 @@ static int __init set_preferred_console(void)
|
|||
}
|
||||
console_initcall(set_preferred_console);
|
||||
#endif /* CONFIG_PPC_MULTIPLATFORM */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
/**
|
||||
* setup_cpu_maps - initialize the following cpu maps:
|
||||
* cpu_possible_map
|
||||
* cpu_present_map
|
||||
* cpu_sibling_map
|
||||
*
|
||||
* Having the possible map set up early allows us to restrict allocations
|
||||
* of things like irqstacks to num_possible_cpus() rather than NR_CPUS.
|
||||
*
|
||||
* We do not initialize the online map here; cpus set their own bits in
|
||||
* cpu_online_map as they come up.
|
||||
*
|
||||
* This function is valid only for Open Firmware systems. finish_device_tree
|
||||
* must be called before using this.
|
||||
*
|
||||
* While we're here, we may as well set the "physical" cpu ids in the paca.
|
||||
*/
|
||||
void __init smp_setup_cpu_maps(void)
|
||||
{
|
||||
struct device_node *dn = NULL;
|
||||
int cpu = 0;
|
||||
int swap_cpuid = 0;
|
||||
|
||||
while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
|
||||
int *intserv;
|
||||
int j, len = sizeof(u32), nthreads = 1;
|
||||
|
||||
intserv = (int *)get_property(dn, "ibm,ppc-interrupt-server#s",
|
||||
&len);
|
||||
if (intserv)
|
||||
nthreads = len / sizeof(int);
|
||||
else {
|
||||
intserv = (int *) get_property(dn, "reg", NULL);
|
||||
if (!intserv)
|
||||
intserv = &cpu; /* assume logical == phys */
|
||||
}
|
||||
|
||||
for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
|
||||
cpu_set(cpu, cpu_present_map);
|
||||
set_hard_smp_processor_id(cpu, intserv[j]);
|
||||
|
||||
if (intserv[j] == boot_cpuid_phys)
|
||||
swap_cpuid = cpu;
|
||||
cpu_set(cpu, cpu_possible_map);
|
||||
cpu++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that
|
||||
* boot cpu is logical 0.
|
||||
*/
|
||||
if (boot_cpuid_phys != get_hard_smp_processor_id(0)) {
|
||||
u32 tmp;
|
||||
tmp = get_hard_smp_processor_id(0);
|
||||
set_hard_smp_processor_id(0, boot_cpuid_phys);
|
||||
set_hard_smp_processor_id(swap_cpuid, tmp);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
/*
|
||||
* On pSeries LPAR, we need to know how many cpus
|
||||
* could possibly be added to this partition.
|
||||
*/
|
||||
if (systemcfg->platform == PLATFORM_PSERIES_LPAR &&
|
||||
(dn = of_find_node_by_path("/rtas"))) {
|
||||
int num_addr_cell, num_size_cell, maxcpus;
|
||||
unsigned int *ireg;
|
||||
|
||||
num_addr_cell = prom_n_addr_cells(dn);
|
||||
num_size_cell = prom_n_size_cells(dn);
|
||||
|
||||
ireg = (unsigned int *)
|
||||
get_property(dn, "ibm,lrdr-capacity", NULL);
|
||||
|
||||
if (!ireg)
|
||||
goto out;
|
||||
|
||||
maxcpus = ireg[num_addr_cell + num_size_cell];
|
||||
|
||||
/* Double maxcpus for processors which have SMT capability */
|
||||
if (cpu_has_feature(CPU_FTR_SMT))
|
||||
maxcpus *= 2;
|
||||
|
||||
if (maxcpus > NR_CPUS) {
|
||||
printk(KERN_WARNING
|
||||
"Partition configured for %d cpus, "
|
||||
"operating system maximum is %d.\n",
|
||||
maxcpus, NR_CPUS);
|
||||
maxcpus = NR_CPUS;
|
||||
} else
|
||||
printk(KERN_INFO "Partition configured for %d cpus.\n",
|
||||
maxcpus);
|
||||
|
||||
for (cpu = 0; cpu < maxcpus; cpu++)
|
||||
cpu_set(cpu, cpu_possible_map);
|
||||
out:
|
||||
of_node_put(dn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the sibling map; assume only two threads per processor.
|
||||
*/
|
||||
for_each_cpu(cpu) {
|
||||
cpu_set(cpu, cpu_sibling_map[cpu]);
|
||||
if (cpu_has_feature(CPU_FTR_SMT))
|
||||
cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
|
||||
}
|
||||
|
||||
systemcfg->processorCount = num_present_cpus();
|
||||
#endif /* CONFIG_PPC64 */
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
|
|
@ -288,6 +288,8 @@ void __init setup_arch(char **cmdline_p)
|
|||
unflatten_device_tree();
|
||||
finish_device_tree();
|
||||
|
||||
smp_setup_cpu_maps();
|
||||
|
||||
#ifdef CONFIG_BOOTX_TEXT
|
||||
init_boot_display();
|
||||
#endif
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
#include <asm/page.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/lmb.h>
|
||||
#include <asm/iSeries/ItLpNaca.h>
|
||||
#include <asm/iseries/it_lp_naca.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/systemcfg.h>
|
||||
#include <asm/xmon.h>
|
||||
|
@ -103,8 +103,6 @@ extern void htab_initialize(void);
|
|||
extern void early_init_devtree(void *flat_dt);
|
||||
extern void unflatten_device_tree(void);
|
||||
|
||||
extern void smp_release_cpus(void);
|
||||
|
||||
int have_of = 1;
|
||||
int boot_cpuid = 0;
|
||||
int boot_cpuid_phys = 0;
|
||||
|
@ -183,120 +181,14 @@ static int __init early_smt_enabled(char *p)
|
|||
}
|
||||
early_param("smt-enabled", early_smt_enabled);
|
||||
|
||||
/**
|
||||
* setup_cpu_maps - initialize the following cpu maps:
|
||||
* cpu_possible_map
|
||||
* cpu_present_map
|
||||
* cpu_sibling_map
|
||||
*
|
||||
* Having the possible map set up early allows us to restrict allocations
|
||||
* of things like irqstacks to num_possible_cpus() rather than NR_CPUS.
|
||||
*
|
||||
* We do not initialize the online map here; cpus set their own bits in
|
||||
* cpu_online_map as they come up.
|
||||
*
|
||||
* This function is valid only for Open Firmware systems. finish_device_tree
|
||||
* must be called before using this.
|
||||
*
|
||||
* While we're here, we may as well set the "physical" cpu ids in the paca.
|
||||
*/
|
||||
static void __init setup_cpu_maps(void)
|
||||
{
|
||||
struct device_node *dn = NULL;
|
||||
int cpu = 0;
|
||||
int swap_cpuid = 0;
|
||||
|
||||
check_smt_enabled();
|
||||
|
||||
while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
|
||||
u32 *intserv;
|
||||
int j, len = sizeof(u32), nthreads;
|
||||
|
||||
intserv = (u32 *)get_property(dn, "ibm,ppc-interrupt-server#s",
|
||||
&len);
|
||||
if (!intserv)
|
||||
intserv = (u32 *)get_property(dn, "reg", NULL);
|
||||
|
||||
nthreads = len / sizeof(u32);
|
||||
|
||||
for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
|
||||
cpu_set(cpu, cpu_present_map);
|
||||
set_hard_smp_processor_id(cpu, intserv[j]);
|
||||
|
||||
if (intserv[j] == boot_cpuid_phys)
|
||||
swap_cpuid = cpu;
|
||||
cpu_set(cpu, cpu_possible_map);
|
||||
cpu++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that
|
||||
* boot cpu is logical 0.
|
||||
*/
|
||||
if (boot_cpuid_phys != get_hard_smp_processor_id(0)) {
|
||||
u32 tmp;
|
||||
tmp = get_hard_smp_processor_id(0);
|
||||
set_hard_smp_processor_id(0, boot_cpuid_phys);
|
||||
set_hard_smp_processor_id(swap_cpuid, tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* On pSeries LPAR, we need to know how many cpus
|
||||
* could possibly be added to this partition.
|
||||
*/
|
||||
if (systemcfg->platform == PLATFORM_PSERIES_LPAR &&
|
||||
(dn = of_find_node_by_path("/rtas"))) {
|
||||
int num_addr_cell, num_size_cell, maxcpus;
|
||||
unsigned int *ireg;
|
||||
|
||||
num_addr_cell = prom_n_addr_cells(dn);
|
||||
num_size_cell = prom_n_size_cells(dn);
|
||||
|
||||
ireg = (unsigned int *)
|
||||
get_property(dn, "ibm,lrdr-capacity", NULL);
|
||||
|
||||
if (!ireg)
|
||||
goto out;
|
||||
|
||||
maxcpus = ireg[num_addr_cell + num_size_cell];
|
||||
|
||||
/* Double maxcpus for processors which have SMT capability */
|
||||
if (cpu_has_feature(CPU_FTR_SMT))
|
||||
maxcpus *= 2;
|
||||
|
||||
if (maxcpus > NR_CPUS) {
|
||||
printk(KERN_WARNING
|
||||
"Partition configured for %d cpus, "
|
||||
"operating system maximum is %d.\n",
|
||||
maxcpus, NR_CPUS);
|
||||
maxcpus = NR_CPUS;
|
||||
} else
|
||||
printk(KERN_INFO "Partition configured for %d cpus.\n",
|
||||
maxcpus);
|
||||
|
||||
for (cpu = 0; cpu < maxcpus; cpu++)
|
||||
cpu_set(cpu, cpu_possible_map);
|
||||
out:
|
||||
of_node_put(dn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the sibling map; assume only two threads per processor.
|
||||
*/
|
||||
for_each_cpu(cpu) {
|
||||
cpu_set(cpu, cpu_sibling_map[cpu]);
|
||||
if (cpu_has_feature(CPU_FTR_SMT))
|
||||
cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
|
||||
}
|
||||
|
||||
systemcfg->processorCount = num_present_cpus();
|
||||
}
|
||||
#else
|
||||
#define check_smt_enabled()
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
extern struct machdep_calls pSeries_md;
|
||||
extern struct machdep_calls pmac_md;
|
||||
extern struct machdep_calls maple_md;
|
||||
extern struct machdep_calls bpa_md;
|
||||
extern struct machdep_calls cell_md;
|
||||
extern struct machdep_calls iseries_md;
|
||||
|
||||
/* Ultimately, stuff them in an elf section like initcalls... */
|
||||
|
@ -310,8 +202,8 @@ static struct machdep_calls __initdata *machines[] = {
|
|||
#ifdef CONFIG_PPC_MAPLE
|
||||
&maple_md,
|
||||
#endif /* CONFIG_PPC_MAPLE */
|
||||
#ifdef CONFIG_PPC_BPA
|
||||
&bpa_md,
|
||||
#ifdef CONFIG_PPC_CELL
|
||||
&cell_md,
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
&iseries_md,
|
||||
|
@ -384,22 +276,50 @@ void __init early_setup(unsigned long dt_ptr)
|
|||
|
||||
DBG("Found, Initializing memory management...\n");
|
||||
|
||||
/*
|
||||
* Initialize stab / SLB management
|
||||
*/
|
||||
if (!firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
stab_initialize(lpaca->stab_real);
|
||||
|
||||
/*
|
||||
* Initialize the MMU Hash table and create the linear mapping
|
||||
* of memory
|
||||
* of memory. Has to be done before stab/slb initialization as
|
||||
* this is currently where the page size encoding is obtained
|
||||
*/
|
||||
htab_initialize();
|
||||
|
||||
/*
|
||||
* Initialize stab / SLB management except on iSeries
|
||||
*/
|
||||
if (!firmware_has_feature(FW_FEATURE_ISERIES)) {
|
||||
if (cpu_has_feature(CPU_FTR_SLB))
|
||||
slb_initialize();
|
||||
else
|
||||
stab_initialize(lpaca->stab_real);
|
||||
}
|
||||
|
||||
DBG(" <- early_setup()\n");
|
||||
}
|
||||
|
||||
|
||||
#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
|
||||
void smp_release_cpus(void)
|
||||
{
|
||||
extern unsigned long __secondary_hold_spinloop;
|
||||
|
||||
DBG(" -> smp_release_cpus()\n");
|
||||
|
||||
/* All secondary cpus are 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.
|
||||
* This is useless but harmless on iSeries, secondaries are already
|
||||
* waiting on their paca spinloops. */
|
||||
|
||||
__secondary_hold_spinloop = 1;
|
||||
mb();
|
||||
|
||||
DBG(" <- smp_release_cpus()\n");
|
||||
}
|
||||
#else
|
||||
#define smp_release_cpus()
|
||||
#endif /* CONFIG_SMP || CONFIG_KEXEC */
|
||||
|
||||
/*
|
||||
* Initialize some remaining members of the ppc64_caches and systemcfg structures
|
||||
* (at least until we get rid of them completely). This is mostly some
|
||||
|
@ -589,17 +509,13 @@ void __init setup_system(void)
|
|||
|
||||
parse_early_param();
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* iSeries has already initialized the cpu maps at this point.
|
||||
*/
|
||||
setup_cpu_maps();
|
||||
check_smt_enabled();
|
||||
smp_setup_cpu_maps();
|
||||
|
||||
/* Release secondary cpus out of their spinloops at 0x60 now that
|
||||
* we can map physical -> logical CPU ids
|
||||
*/
|
||||
smp_release_cpus();
|
||||
#endif
|
||||
|
||||
printk("Starting Linux PPC64 %s\n", system_utsname.version);
|
||||
|
||||
|
@ -631,23 +547,6 @@ static int ppc64_panic_event(struct notifier_block *this,
|
|||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
/*
|
||||
* On iSeries we just parse the mem=X option from the command line.
|
||||
* On pSeries it's a bit more complicated, see prom_init_mem()
|
||||
*/
|
||||
static int __init early_parsemem(char *p)
|
||||
{
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
memory_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_param("mem", early_parsemem);
|
||||
#endif /* CONFIG_PPC_ISERIES */
|
||||
|
||||
#ifdef CONFIG_IRQSTACKS
|
||||
static void __init irqstack_early_init(void)
|
||||
{
|
||||
|
@ -658,10 +557,12 @@ static void __init irqstack_early_init(void)
|
|||
* SLB misses on them.
|
||||
*/
|
||||
for_each_cpu(i) {
|
||||
softirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
|
||||
THREAD_SIZE, 0x10000000));
|
||||
hardirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
|
||||
THREAD_SIZE, 0x10000000));
|
||||
softirq_ctx[i] = (struct thread_info *)
|
||||
__va(lmb_alloc_base(THREAD_SIZE,
|
||||
THREAD_SIZE, 0x10000000));
|
||||
hardirq_ctx[i] = (struct thread_info *)
|
||||
__va(lmb_alloc_base(THREAD_SIZE,
|
||||
THREAD_SIZE, 0x10000000));
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -689,8 +590,8 @@ static void __init emergency_stack_init(void)
|
|||
limit = min(0x10000000UL, lmb.rmo_size);
|
||||
|
||||
for_each_cpu(i)
|
||||
paca[i].emergency_sp = __va(lmb_alloc_base(PAGE_SIZE, 128,
|
||||
limit)) + PAGE_SIZE;
|
||||
paca[i].emergency_sp =
|
||||
__va(lmb_alloc_base(HW_PAGE_SIZE, 128, limit)) + HW_PAGE_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#ifdef CONFIG_PPC64
|
||||
#include <asm/ppc32.h>
|
||||
#include "ppc32.h"
|
||||
#include <asm/ppcdebug.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/vdso.h>
|
||||
|
|
|
@ -22,11 +22,11 @@ enum {
|
|||
};
|
||||
|
||||
static struct {
|
||||
volatile long tb;
|
||||
volatile long mark;
|
||||
volatile u64 tb;
|
||||
volatile u64 mark;
|
||||
volatile int cmd;
|
||||
volatile int handshake;
|
||||
int filler[3];
|
||||
int filler[2];
|
||||
|
||||
volatile int ack;
|
||||
int filler2[7];
|
||||
|
@ -36,89 +36,80 @@ static struct {
|
|||
|
||||
static volatile int running;
|
||||
|
||||
static void __devinit
|
||||
enter_contest( long mark, long add )
|
||||
static void __devinit enter_contest(u64 mark, long add)
|
||||
{
|
||||
while( (long)(mftb() - mark) < 0 )
|
||||
while (get_tb() < mark)
|
||||
tbsync->race_result = add;
|
||||
}
|
||||
|
||||
void __devinit
|
||||
smp_generic_take_timebase( void )
|
||||
void __devinit smp_generic_take_timebase(void)
|
||||
{
|
||||
int cmd;
|
||||
long tb;
|
||||
u64 tb;
|
||||
|
||||
local_irq_disable();
|
||||
while( !running )
|
||||
;
|
||||
while (!running)
|
||||
barrier();
|
||||
rmb();
|
||||
|
||||
for( ;; ) {
|
||||
for (;;) {
|
||||
tbsync->ack = 1;
|
||||
while( !tbsync->handshake )
|
||||
;
|
||||
while (!tbsync->handshake)
|
||||
barrier();
|
||||
rmb();
|
||||
|
||||
cmd = tbsync->cmd;
|
||||
tb = tbsync->tb;
|
||||
mb();
|
||||
tbsync->ack = 0;
|
||||
if( cmd == kExit )
|
||||
return;
|
||||
if (cmd == kExit)
|
||||
break;
|
||||
|
||||
if( cmd == kSetAndTest ) {
|
||||
while( tbsync->handshake )
|
||||
;
|
||||
asm volatile ("mttbl %0" :: "r" (tb & 0xfffffffful) );
|
||||
asm volatile ("mttbu %0" :: "r" (tb >> 32) );
|
||||
} else {
|
||||
while( tbsync->handshake )
|
||||
;
|
||||
}
|
||||
enter_contest( tbsync->mark, -1 );
|
||||
while (tbsync->handshake)
|
||||
barrier();
|
||||
if (cmd == kSetAndTest)
|
||||
set_tb(tb >> 32, tb & 0xfffffffful);
|
||||
enter_contest(tbsync->mark, -1);
|
||||
}
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
static int __devinit
|
||||
start_contest( int cmd, long offset, long num )
|
||||
static int __devinit start_contest(int cmd, long offset, int num)
|
||||
{
|
||||
int i, score=0;
|
||||
long tb, mark;
|
||||
u64 tb;
|
||||
long mark;
|
||||
|
||||
tbsync->cmd = cmd;
|
||||
|
||||
local_irq_disable();
|
||||
for( i=-3; i<num; ) {
|
||||
tb = (long)mftb() + 400;
|
||||
for (i = -3; i < num; ) {
|
||||
tb = get_tb() + 400;
|
||||
tbsync->tb = tb + offset;
|
||||
tbsync->mark = mark = tb + 400;
|
||||
|
||||
wmb();
|
||||
|
||||
tbsync->handshake = 1;
|
||||
while( tbsync->ack )
|
||||
;
|
||||
while (tbsync->ack)
|
||||
barrier();
|
||||
|
||||
while( (long)(mftb() - tb) <= 0 )
|
||||
;
|
||||
while (get_tb() <= tb)
|
||||
barrier();
|
||||
tbsync->handshake = 0;
|
||||
enter_contest( mark, 1 );
|
||||
enter_contest(mark, 1);
|
||||
|
||||
while( !tbsync->ack )
|
||||
;
|
||||
while (!tbsync->ack)
|
||||
barrier();
|
||||
|
||||
if ((tbsync->tb ^ (long)mftb()) & 0x8000000000000000ul)
|
||||
continue;
|
||||
if( i++ > 0 )
|
||||
if (i++ > 0)
|
||||
score += tbsync->race_result;
|
||||
}
|
||||
local_irq_enable();
|
||||
return score;
|
||||
}
|
||||
|
||||
void __devinit
|
||||
smp_generic_give_timebase( void )
|
||||
void __devinit smp_generic_give_timebase(void)
|
||||
{
|
||||
int i, score, score2, old, min=0, max=5000, offset=1000;
|
||||
|
||||
|
@ -130,14 +121,14 @@ smp_generic_give_timebase( void )
|
|||
mb();
|
||||
running = 1;
|
||||
|
||||
while( !tbsync->ack )
|
||||
;
|
||||
while (!tbsync->ack)
|
||||
barrier();
|
||||
|
||||
printk("Got ack\n");
|
||||
|
||||
/* binary search */
|
||||
for( old=-1 ; old != offset ; offset=(min+max)/2 ) {
|
||||
score = start_contest( kSetAndTest, offset, NUM_ITER );
|
||||
for (old = -1; old != offset ; offset = (min+max) / 2) {
|
||||
score = start_contest(kSetAndTest, offset, NUM_ITER);
|
||||
|
||||
printk("score %d, offset %d\n", score, offset );
|
||||
|
||||
|
@ -147,21 +138,22 @@ smp_generic_give_timebase( void )
|
|||
min = offset;
|
||||
old = offset;
|
||||
}
|
||||
score = start_contest( kSetAndTest, min, NUM_ITER );
|
||||
score2 = start_contest( kSetAndTest, max, NUM_ITER );
|
||||
score = start_contest(kSetAndTest, min, NUM_ITER);
|
||||
score2 = start_contest(kSetAndTest, max, NUM_ITER);
|
||||
|
||||
printk( "Min %d (score %d), Max %d (score %d)\n", min, score, max, score2 );
|
||||
score = abs( score );
|
||||
score2 = abs( score2 );
|
||||
printk("Min %d (score %d), Max %d (score %d)\n",
|
||||
min, score, max, score2);
|
||||
score = abs(score);
|
||||
score2 = abs(score2);
|
||||
offset = (score < score2) ? min : max;
|
||||
|
||||
/* guard against inaccurate mttb */
|
||||
for( i=0; i<10; i++ ) {
|
||||
start_contest( kSetAndTest, offset, NUM_ITER/10 );
|
||||
for (i = 0; i < 10; i++) {
|
||||
start_contest(kSetAndTest, offset, NUM_ITER/10);
|
||||
|
||||
if( (score2=start_contest(kTest, offset, NUM_ITER)) < 0 )
|
||||
if ((score2 = start_contest(kTest, offset, NUM_ITER)) < 0)
|
||||
score2 = -score2;
|
||||
if( score2 <= score || score2 < 20 )
|
||||
if (score2 <= score || score2 < 20)
|
||||
break;
|
||||
}
|
||||
printk("Final offset: %d (%d/%d)\n", offset, score2, NUM_ITER );
|
||||
|
@ -170,10 +162,10 @@ smp_generic_give_timebase( void )
|
|||
tbsync->cmd = kExit;
|
||||
wmb();
|
||||
tbsync->handshake = 1;
|
||||
while( tbsync->ack )
|
||||
;
|
||||
while (tbsync->ack)
|
||||
barrier();
|
||||
tbsync->handshake = 0;
|
||||
kfree( tbsync );
|
||||
kfree(tbsync);
|
||||
tbsync = NULL;
|
||||
running = 0;
|
||||
}
|
|
@ -39,13 +39,18 @@
|
|||
#include <asm/pgtable.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/paca.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/xmon.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/abs_addr.h>
|
||||
#include <asm/mpic.h>
|
||||
#ifdef CONFIG_PPC64
|
||||
#include <asm/paca.h>
|
||||
#endif
|
||||
|
||||
int smp_hw_index[NR_CPUS];
|
||||
struct thread_info *secondary_ti;
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
|
@ -60,6 +65,7 @@ cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
|
|||
EXPORT_SYMBOL(cpu_online_map);
|
||||
EXPORT_SYMBOL(cpu_possible_map);
|
||||
|
||||
/* SMP operations for this machine */
|
||||
struct smp_ops_t *smp_ops;
|
||||
|
||||
static volatile unsigned int cpu_callin_map[NR_CPUS];
|
||||
|
@ -89,7 +95,9 @@ void __devinit smp_mpic_setup_cpu(int cpu)
|
|||
{
|
||||
mpic_setup_this_cpu();
|
||||
}
|
||||
#endif /* CONFIG_MPIC */
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
void __devinit smp_generic_kick_cpu(int nr)
|
||||
{
|
||||
BUG_ON(nr < 0 || nr >= NR_CPUS);
|
||||
|
@ -102,8 +110,7 @@ void __devinit smp_generic_kick_cpu(int nr)
|
|||
paca[nr].cpu_start = 1;
|
||||
smp_mb();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MPIC */
|
||||
#endif
|
||||
|
||||
void smp_message_recv(int msg, struct pt_regs *regs)
|
||||
{
|
||||
|
@ -111,15 +118,10 @@ void smp_message_recv(int msg, struct pt_regs *regs)
|
|||
case PPC_MSG_CALL_FUNCTION:
|
||||
smp_call_function_interrupt();
|
||||
break;
|
||||
case PPC_MSG_RESCHEDULE:
|
||||
case PPC_MSG_RESCHEDULE:
|
||||
/* XXX Do we have to do this? */
|
||||
set_need_resched();
|
||||
break;
|
||||
#if 0
|
||||
case PPC_MSG_MIGRATE_TASK:
|
||||
/* spare */
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_DEBUGGER
|
||||
case PPC_MSG_DEBUGGER_BREAK:
|
||||
debugger_ipi(regs);
|
||||
|
@ -171,8 +173,8 @@ static struct call_data_struct {
|
|||
int wait;
|
||||
} *call_data;
|
||||
|
||||
/* delay of at least 8 seconds on 1GHz cpu */
|
||||
#define SMP_CALL_TIMEOUT (1UL << (30 + 3))
|
||||
/* delay of at least 8 seconds */
|
||||
#define SMP_CALL_TIMEOUT 8
|
||||
|
||||
/*
|
||||
* This function sends a 'generic call function' IPI to all other CPUs
|
||||
|
@ -194,7 +196,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
|
|||
{
|
||||
struct call_data_struct data;
|
||||
int ret = -1, cpus;
|
||||
unsigned long timeout;
|
||||
u64 timeout;
|
||||
|
||||
/* Can deadlock when called with interrupts disabled */
|
||||
WARN_ON(irqs_disabled());
|
||||
|
@ -220,11 +222,12 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
|
|||
/* Send a message to all other CPUs and wait for them to respond */
|
||||
smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION);
|
||||
|
||||
timeout = get_tb() + (u64) SMP_CALL_TIMEOUT * tb_ticks_per_sec;
|
||||
|
||||
/* Wait for response */
|
||||
timeout = SMP_CALL_TIMEOUT;
|
||||
while (atomic_read(&data.started) != cpus) {
|
||||
HMT_low();
|
||||
if (--timeout == 0) {
|
||||
if (get_tb() >= timeout) {
|
||||
printk("smp_call_function on cpu %d: other cpus not "
|
||||
"responding (%d)\n", smp_processor_id(),
|
||||
atomic_read(&data.started));
|
||||
|
@ -234,10 +237,9 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
|
|||
}
|
||||
|
||||
if (wait) {
|
||||
timeout = SMP_CALL_TIMEOUT;
|
||||
while (atomic_read(&data.finished) != cpus) {
|
||||
HMT_low();
|
||||
if (--timeout == 0) {
|
||||
if (get_tb() >= timeout) {
|
||||
printk("smp_call_function on cpu %d: other "
|
||||
"cpus not finishing (%d/%d)\n",
|
||||
smp_processor_id(),
|
||||
|
@ -251,7 +253,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
|
|||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
out:
|
||||
call_data = NULL;
|
||||
HMT_medium();
|
||||
spin_unlock(&call_lock);
|
||||
|
@ -313,8 +315,11 @@ static void __init smp_create_idle(unsigned int cpu)
|
|||
p = fork_idle(cpu);
|
||||
if (IS_ERR(p))
|
||||
panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
|
||||
#ifdef CONFIG_PPC64
|
||||
paca[cpu].__current = p;
|
||||
#endif
|
||||
current_set[cpu] = p->thread_info;
|
||||
p->thread_info->cpu = cpu;
|
||||
}
|
||||
|
||||
void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
|
@ -333,18 +338,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
|||
smp_store_cpu_info(boot_cpuid);
|
||||
cpu_callin_map[boot_cpuid] = 1;
|
||||
|
||||
#ifndef CONFIG_PPC_ISERIES
|
||||
paca[boot_cpuid].next_jiffy_update_tb = tb_last_stamp = get_tb();
|
||||
|
||||
/*
|
||||
* Should update do_gtod.stamp_xsec.
|
||||
* For now we leave it which means the time can be some
|
||||
* number of msecs off until someone does a settimeofday()
|
||||
*/
|
||||
do_gtod.varp->tb_orig_stamp = tb_last_stamp;
|
||||
systemcfg->tb_orig_stamp = tb_last_stamp;
|
||||
#endif
|
||||
|
||||
max_cpus = smp_ops->probe();
|
||||
|
||||
smp_space_timers(max_cpus);
|
||||
|
@ -359,8 +352,9 @@ void __devinit smp_prepare_boot_cpu(void)
|
|||
BUG_ON(smp_processor_id() != boot_cpuid);
|
||||
|
||||
cpu_set(boot_cpuid, cpu_online_map);
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
paca[boot_cpuid].__current = current;
|
||||
#endif
|
||||
current_set[boot_cpuid] = current->thread_info;
|
||||
}
|
||||
|
||||
|
@ -444,13 +438,16 @@ int __devinit __cpu_up(unsigned int cpu)
|
|||
{
|
||||
int c;
|
||||
|
||||
secondary_ti = current_set[cpu];
|
||||
if (!cpu_enable(cpu))
|
||||
return 0;
|
||||
|
||||
if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))
|
||||
return -EINVAL;
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
paca[cpu].default_decr = tb_ticks_per_jiffy;
|
||||
#endif
|
||||
|
||||
/* Make sure callin-map entry is 0 (can be leftover a CPU
|
||||
* hotplug
|
||||
|
@ -513,7 +510,7 @@ int __devinit start_secondary(void *unused)
|
|||
current->active_mm = &init_mm;
|
||||
|
||||
smp_store_cpu_info(cpu);
|
||||
set_dec(paca[cpu].default_decr);
|
||||
set_dec(tb_ticks_per_jiffy);
|
||||
cpu_callin_map[cpu] = 1;
|
||||
|
||||
smp_ops->setup_cpu(cpu);
|
|
@ -66,8 +66,8 @@
|
|||
#include <asm/firmware.h>
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
#include <asm/iSeries/ItLpQueue.h>
|
||||
#include <asm/iSeries/HvCallXm.h>
|
||||
#include <asm/iseries/it_lp_queue.h>
|
||||
#include <asm/iseries/hv_call_xm.h>
|
||||
#endif
|
||||
|
||||
/* keep track of when we need to update the rtc */
|
||||
|
|
|
@ -147,8 +147,8 @@ int die(const char *str, struct pt_regs *regs, long err)
|
|||
printk("POWERMAC ");
|
||||
nl = 1;
|
||||
break;
|
||||
case PLATFORM_BPA:
|
||||
printk("BPA ");
|
||||
case PLATFORM_CELL:
|
||||
printk("CELL ");
|
||||
nl = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -749,22 +749,22 @@ static int check_bug_trap(struct pt_regs *regs)
|
|||
if (bug->line & BUG_WARNING_TRAP) {
|
||||
/* this is a WARN_ON rather than BUG/BUG_ON */
|
||||
#ifdef CONFIG_XMON
|
||||
xmon_printf(KERN_ERR "Badness in %s at %s:%d\n",
|
||||
xmon_printf(KERN_ERR "Badness in %s at %s:%ld\n",
|
||||
bug->function, bug->file,
|
||||
bug->line & ~BUG_WARNING_TRAP);
|
||||
#endif /* CONFIG_XMON */
|
||||
printk(KERN_ERR "Badness in %s at %s:%d\n",
|
||||
printk(KERN_ERR "Badness in %s at %s:%ld\n",
|
||||
bug->function, bug->file,
|
||||
bug->line & ~BUG_WARNING_TRAP);
|
||||
dump_stack();
|
||||
return 1;
|
||||
}
|
||||
#ifdef CONFIG_XMON
|
||||
xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%d!\n",
|
||||
xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
|
||||
bug->function, bug->file, bug->line);
|
||||
xmon(regs);
|
||||
#endif /* CONFIG_XMON */
|
||||
printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n",
|
||||
printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
|
||||
bug->function, bug->file, bug->line);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -3,9 +3,12 @@
|
|||
#include <asm/page.h>
|
||||
#else
|
||||
#define PAGE_SIZE 4096
|
||||
#define KERNELBASE CONFIG_KERNEL_START
|
||||
#endif
|
||||
#include <asm-generic/vmlinux.lds.h>
|
||||
|
||||
ENTRY(_stext)
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
OUTPUT_ARCH(powerpc:common64)
|
||||
jiffies = jiffies_64;
|
||||
|
@ -21,33 +24,9 @@ SECTIONS
|
|||
*(.exit.data)
|
||||
}
|
||||
|
||||
. = KERNELBASE;
|
||||
|
||||
/* Read-only sections, merged into text segment: */
|
||||
#ifdef CONFIG_PPC32
|
||||
. = + 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) }
|
||||
/* .init : { *(.init) } =0*/
|
||||
.plt : { *(.plt) }
|
||||
#endif
|
||||
.text : {
|
||||
*(.text .text.*)
|
||||
SCHED_TEXT
|
||||
|
|
|
@ -3,13 +3,14 @@
|
|||
#
|
||||
|
||||
ifeq ($(CONFIG_PPC_MERGE),y)
|
||||
obj-y := string.o
|
||||
obj-y := string.o strcase.o
|
||||
obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o
|
||||
endif
|
||||
|
||||
obj-y += strcase.o
|
||||
obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o
|
||||
obj-y += bitops.o
|
||||
obj-$(CONFIG_PPC64) += checksum_64.o copypage_64.o copyuser_64.o \
|
||||
memcpy_64.o usercopy_64.o mem_64.o
|
||||
memcpy_64.o usercopy_64.o mem_64.o string.o \
|
||||
strcase.o
|
||||
obj-$(CONFIG_PPC_ISERIES) += e2a.o
|
||||
obj-$(CONFIG_XMON) += sstep.o
|
||||
|
||||
|
|
|
@ -1,79 +1,40 @@
|
|||
/*
|
||||
* These are too big to be inlined.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/bitops.h>
|
||||
|
||||
unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
|
||||
unsigned long offset)
|
||||
{
|
||||
const unsigned long *p = addr + (offset >> 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) /* Are any bits zero? */
|
||||
return result + size; /* Nope. */
|
||||
found_middle:
|
||||
return result + ffz(tmp);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(find_next_zero_bit);
|
||||
|
||||
/**
|
||||
* find_next_bit - find the next set bit in a memory region
|
||||
* @addr: The address to base the search on
|
||||
* @offset: The bitnumber to start searching at
|
||||
* @size: The maximum size to search
|
||||
*/
|
||||
unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
|
||||
unsigned long offset)
|
||||
{
|
||||
const unsigned long *p = addr + (offset >> 6);
|
||||
unsigned long result = offset & ~63UL;
|
||||
const unsigned long *p = addr + BITOP_WORD(offset);
|
||||
unsigned long result = offset & ~(BITS_PER_LONG-1);
|
||||
unsigned long tmp;
|
||||
|
||||
if (offset >= size)
|
||||
return size;
|
||||
size -= result;
|
||||
offset &= 63UL;
|
||||
offset %= BITS_PER_LONG;
|
||||
if (offset) {
|
||||
tmp = *(p++);
|
||||
tmp &= (~0UL << offset);
|
||||
if (size < 64)
|
||||
if (size < BITS_PER_LONG)
|
||||
goto found_first;
|
||||
if (tmp)
|
||||
goto found_middle;
|
||||
size -= 64;
|
||||
result += 64;
|
||||
size -= BITS_PER_LONG;
|
||||
result += BITS_PER_LONG;
|
||||
}
|
||||
while (size & ~63UL) {
|
||||
while (size & ~(BITS_PER_LONG-1)) {
|
||||
if ((tmp = *(p++)))
|
||||
goto found_middle;
|
||||
result += 64;
|
||||
size -= 64;
|
||||
result += BITS_PER_LONG;
|
||||
size -= BITS_PER_LONG;
|
||||
}
|
||||
if (!size)
|
||||
return result;
|
||||
|
@ -86,9 +47,52 @@ found_first:
|
|||
found_middle:
|
||||
return result + __ffs(tmp);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(find_next_bit);
|
||||
|
||||
/*
|
||||
* This implementation of find_{first,next}_zero_bit was stolen from
|
||||
* Linus' asm-alpha/bitops.h.
|
||||
*/
|
||||
unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
|
||||
unsigned long offset)
|
||||
{
|
||||
const unsigned long *p = addr + BITOP_WORD(offset);
|
||||
unsigned long result = offset & ~(BITS_PER_LONG-1);
|
||||
unsigned long tmp;
|
||||
|
||||
if (offset >= size)
|
||||
return size;
|
||||
size -= result;
|
||||
offset %= BITS_PER_LONG;
|
||||
if (offset) {
|
||||
tmp = *(p++);
|
||||
tmp |= ~0UL >> (BITS_PER_LONG - offset);
|
||||
if (size < BITS_PER_LONG)
|
||||
goto found_first;
|
||||
if (~tmp)
|
||||
goto found_middle;
|
||||
size -= BITS_PER_LONG;
|
||||
result += BITS_PER_LONG;
|
||||
}
|
||||
while (size & ~(BITS_PER_LONG-1)) {
|
||||
if (~(tmp = *(p++)))
|
||||
goto found_middle;
|
||||
result += BITS_PER_LONG;
|
||||
size -= BITS_PER_LONG;
|
||||
}
|
||||
if (!size)
|
||||
return result;
|
||||
tmp = *p;
|
||||
|
||||
found_first:
|
||||
tmp |= ~0UL << size;
|
||||
if (tmp == ~0UL) /* Are any bits zero? */
|
||||
return result + size; /* Nope. */
|
||||
found_middle:
|
||||
return result + ffz(tmp);
|
||||
}
|
||||
EXPORT_SYMBOL(find_next_zero_bit);
|
||||
|
||||
static inline unsigned int ext2_ilog2(unsigned int x)
|
||||
{
|
||||
int lz;
|
||||
|
@ -106,8 +110,8 @@ static inline unsigned int ext2_ffz(unsigned int x)
|
|||
return rc;
|
||||
}
|
||||
|
||||
unsigned long find_next_zero_le_bit(const unsigned long *addr, unsigned long size,
|
||||
unsigned long offset)
|
||||
unsigned long find_next_zero_le_bit(const unsigned long *addr,
|
||||
unsigned long size, unsigned long offset)
|
||||
{
|
||||
const unsigned int *p = ((const unsigned int *)addr) + (offset >> 5);
|
||||
unsigned int result = offset & ~31;
|
||||
|
@ -143,5 +147,4 @@ found_first:
|
|||
found_middle:
|
||||
return result + ext2_ffz(tmp);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(find_next_zero_le_bit);
|
|
@ -11,7 +11,7 @@
|
|||
#include <asm/processor.h>
|
||||
#include <asm/ppc_asm.h>
|
||||
|
||||
_GLOBAL(copy_page)
|
||||
_GLOBAL(copy_4K_page)
|
||||
std r31,-8(1)
|
||||
std r30,-16(1)
|
||||
std r29,-24(1)
|
||||
|
|
|
@ -24,7 +24,7 @@ _GLOBAL(__copy_tofrom_user)
|
|||
std r4,-16(r1)
|
||||
std r5,-8(r1)
|
||||
dcbt 0,r4
|
||||
beq .Lcopy_page
|
||||
beq .Lcopy_page_4K
|
||||
andi. r6,r6,7
|
||||
mtcrf 0x01,r5
|
||||
blt cr1,.Lshort_copy
|
||||
|
@ -366,7 +366,7 @@ _GLOBAL(__copy_tofrom_user)
|
|||
* above (following the .Ldst_aligned label) but it runs slightly
|
||||
* slower on POWER3.
|
||||
*/
|
||||
.Lcopy_page:
|
||||
.Lcopy_page_4K:
|
||||
std r31,-32(1)
|
||||
std r30,-40(1)
|
||||
std r29,-48(1)
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
/* waiting for a spinlock... */
|
||||
#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
|
||||
#include <asm/hvcall.h>
|
||||
#include <asm/iSeries/HvCall.h>
|
||||
#include <asm/iseries/hv_call.h>
|
||||
|
||||
void __spin_yield(raw_spinlock_t *lock)
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* ppc64 MMU hashtable management routines
|
||||
*
|
||||
* (c) Copyright IBM Corp. 2003
|
||||
* (c) Copyright IBM Corp. 2003, 2005
|
||||
*
|
||||
* Maintained by: Benjamin Herrenschmidt
|
||||
* <benh@kernel.crashing.org>
|
||||
|
@ -10,6 +10,7 @@
|
|||
* described in the kernel's COPYING file.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <asm/reg.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/mmu.h>
|
||||
|
@ -42,14 +43,24 @@
|
|||
/* Save non-volatile offsets */
|
||||
#define STK_REG(i) (112 + ((i)-14)*8)
|
||||
|
||||
|
||||
#ifndef CONFIG_PPC_64K_PAGES
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* 4K SW & 4K HW pages implementation *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* _hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
|
||||
* pte_t *ptep, unsigned long trap, int local)
|
||||
* _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
|
||||
* pte_t *ptep, unsigned long trap, int local)
|
||||
*
|
||||
* Adds a page to the hash table. This is the non-LPAR version for now
|
||||
* Adds a 4K page to the hash table in a segment of 4K pages only
|
||||
*/
|
||||
|
||||
_GLOBAL(__hash_page)
|
||||
_GLOBAL(__hash_page_4K)
|
||||
mflr r0
|
||||
std r0,16(r1)
|
||||
stdu r1,-STACKFRAMESIZE(r1)
|
||||
|
@ -88,7 +99,8 @@ _GLOBAL(__hash_page)
|
|||
/* If so, just bail out and refault if needed. Someone else
|
||||
* is changing this PTE anyway and might hash it.
|
||||
*/
|
||||
bne- bail_ok
|
||||
bne- htab_bail_ok
|
||||
|
||||
/* Prepare new PTE value (turn access RW into DIRTY, then
|
||||
* add BUSY,HASHPTE and ACCESSED)
|
||||
*/
|
||||
|
@ -118,10 +130,10 @@ _GLOBAL(__hash_page)
|
|||
|
||||
/* Convert linux PTE bits into HW equivalents */
|
||||
andi. r3,r30,0x1fe /* Get basic set of flags */
|
||||
xori r3,r3,HW_NO_EXEC /* _PAGE_EXEC -> NOEXEC */
|
||||
xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */
|
||||
rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
|
||||
rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */
|
||||
and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY -> r0 bit 30 */
|
||||
and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
|
||||
andc r0,r30,r0 /* r0 = pte & ~r0 */
|
||||
rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */
|
||||
|
||||
|
@ -158,19 +170,21 @@ htab_insert_pte:
|
|||
andc r30,r30,r0
|
||||
ori r30,r30,_PAGE_HASHPTE
|
||||
|
||||
/* page number in r5 */
|
||||
rldicl r5,r31,64-PTE_SHIFT,PTE_SHIFT
|
||||
/* physical address r5 */
|
||||
rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
|
||||
sldi r5,r5,PAGE_SHIFT
|
||||
|
||||
/* Calculate primary group hash */
|
||||
and r0,r28,r27
|
||||
rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
|
||||
rldicr r3,r0,3,63-3 /* r3 = (hash & mask) << 3 */
|
||||
|
||||
/* Call ppc_md.hpte_insert */
|
||||
ld r7,STK_PARM(r4)(r1) /* Retreive new pp bits */
|
||||
ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */
|
||||
mr r4,r29 /* Retreive va */
|
||||
li r6,0 /* no vflags */
|
||||
li r7,0 /* !bolted, !secondary */
|
||||
li r8,MMU_PAGE_4K /* page size */
|
||||
_GLOBAL(htab_call_hpte_insert1)
|
||||
bl . /* Will be patched by htab_finish_init() */
|
||||
bl . /* Patched by htab_finish_init() */
|
||||
cmpdi 0,r3,0
|
||||
bge htab_pte_insert_ok /* Insertion successful */
|
||||
cmpdi 0,r3,-2 /* Critical failure */
|
||||
|
@ -178,19 +192,21 @@ _GLOBAL(htab_call_hpte_insert1)
|
|||
|
||||
/* Now try secondary slot */
|
||||
|
||||
/* page number in r5 */
|
||||
rldicl r5,r31,64-PTE_SHIFT,PTE_SHIFT
|
||||
/* physical address r5 */
|
||||
rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
|
||||
sldi r5,r5,PAGE_SHIFT
|
||||
|
||||
/* Calculate secondary group hash */
|
||||
andc r0,r27,r28
|
||||
rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */
|
||||
|
||||
/* Call ppc_md.hpte_insert */
|
||||
ld r7,STK_PARM(r4)(r1) /* Retreive new pp bits */
|
||||
ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */
|
||||
mr r4,r29 /* Retreive va */
|
||||
li r6,HPTE_V_SECONDARY@l /* secondary slot */
|
||||
li r7,HPTE_V_SECONDARY /* !bolted, secondary */
|
||||
li r8,MMU_PAGE_4K /* page size */
|
||||
_GLOBAL(htab_call_hpte_insert2)
|
||||
bl . /* Will be patched by htab_finish_init() */
|
||||
bl . /* Patched by htab_finish_init() */
|
||||
cmpdi 0,r3,0
|
||||
bge+ htab_pte_insert_ok /* Insertion successful */
|
||||
cmpdi 0,r3,-2 /* Critical failure */
|
||||
|
@ -207,14 +223,14 @@ _GLOBAL(htab_call_hpte_insert2)
|
|||
rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
|
||||
/* Call ppc_md.hpte_remove */
|
||||
_GLOBAL(htab_call_hpte_remove)
|
||||
bl . /* Will be patched by htab_finish_init() */
|
||||
bl . /* Patched by htab_finish_init() */
|
||||
|
||||
/* Try all again */
|
||||
b htab_insert_pte
|
||||
|
||||
bail_ok:
|
||||
htab_bail_ok:
|
||||
li r3,0
|
||||
b bail
|
||||
b htab_bail
|
||||
|
||||
htab_pte_insert_ok:
|
||||
/* Insert slot number & secondary bit in PTE */
|
||||
|
@ -227,7 +243,7 @@ htab_write_out_pte:
|
|||
ld r6,STK_PARM(r6)(r1)
|
||||
std r30,0(r6)
|
||||
li r3, 0
|
||||
bail:
|
||||
htab_bail:
|
||||
ld r27,STK_REG(r27)(r1)
|
||||
ld r28,STK_REG(r28)(r1)
|
||||
ld r29,STK_REG(r29)(r1)
|
||||
|
@ -256,10 +272,10 @@ htab_modify_pte:
|
|||
|
||||
/* Call ppc_md.hpte_updatepp */
|
||||
mr r5,r29 /* va */
|
||||
li r6,0 /* large is 0 */
|
||||
li r6,MMU_PAGE_4K /* page size */
|
||||
ld r7,STK_PARM(r8)(r1) /* get "local" param */
|
||||
_GLOBAL(htab_call_hpte_updatepp)
|
||||
bl . /* Will be patched by htab_finish_init() */
|
||||
bl . /* Patched by htab_finish_init() */
|
||||
|
||||
/* if we failed because typically the HPTE wasn't really here
|
||||
* we try an insertion.
|
||||
|
@ -276,13 +292,556 @@ htab_wrong_access:
|
|||
/* Bail out clearing reservation */
|
||||
stdcx. r31,0,r6
|
||||
li r3,1
|
||||
b bail
|
||||
b htab_bail
|
||||
|
||||
htab_pte_insert_failure:
|
||||
/* Bail out restoring old PTE */
|
||||
ld r6,STK_PARM(r6)(r1)
|
||||
std r31,0(r6)
|
||||
li r3,-1
|
||||
b bail
|
||||
b htab_bail
|
||||
|
||||
|
||||
#else /* CONFIG_PPC_64K_PAGES */
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* 64K SW & 4K or 64K HW in a 4K segment pages implementation *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
/* _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
|
||||
* pte_t *ptep, unsigned long trap, int local)
|
||||
*/
|
||||
|
||||
/*
|
||||
* For now, we do NOT implement Admixed pages
|
||||
*/
|
||||
_GLOBAL(__hash_page_4K)
|
||||
mflr r0
|
||||
std r0,16(r1)
|
||||
stdu r1,-STACKFRAMESIZE(r1)
|
||||
/* Save all params that we need after a function call */
|
||||
std r6,STK_PARM(r6)(r1)
|
||||
std r8,STK_PARM(r8)(r1)
|
||||
|
||||
/* Add _PAGE_PRESENT to access */
|
||||
ori r4,r4,_PAGE_PRESENT
|
||||
|
||||
/* Save non-volatile registers.
|
||||
* r31 will hold "old PTE"
|
||||
* r30 is "new PTE"
|
||||
* r29 is "va"
|
||||
* r28 is a hash value
|
||||
* r27 is hashtab mask (maybe dynamic patched instead ?)
|
||||
* r26 is the hidx mask
|
||||
* r25 is the index in combo page
|
||||
*/
|
||||
std r25,STK_REG(r25)(r1)
|
||||
std r26,STK_REG(r26)(r1)
|
||||
std r27,STK_REG(r27)(r1)
|
||||
std r28,STK_REG(r28)(r1)
|
||||
std r29,STK_REG(r29)(r1)
|
||||
std r30,STK_REG(r30)(r1)
|
||||
std r31,STK_REG(r31)(r1)
|
||||
|
||||
/* Step 1:
|
||||
*
|
||||
* Check permissions, atomically mark the linux PTE busy
|
||||
* and hashed.
|
||||
*/
|
||||
1:
|
||||
ldarx r31,0,r6
|
||||
/* Check access rights (access & ~(pte_val(*ptep))) */
|
||||
andc. r0,r4,r31
|
||||
bne- htab_wrong_access
|
||||
/* Check if PTE is busy */
|
||||
andi. r0,r31,_PAGE_BUSY
|
||||
/* If so, just bail out and refault if needed. Someone else
|
||||
* is changing this PTE anyway and might hash it.
|
||||
*/
|
||||
bne- htab_bail_ok
|
||||
/* Prepare new PTE value (turn access RW into DIRTY, then
|
||||
* add BUSY and ACCESSED)
|
||||
*/
|
||||
rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */
|
||||
or r30,r30,r31
|
||||
ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE
|
||||
/* Write the linux PTE atomically (setting busy) */
|
||||
stdcx. r30,0,r6
|
||||
bne- 1b
|
||||
isync
|
||||
|
||||
/* Step 2:
|
||||
*
|
||||
* Insert/Update the HPTE in the hash table. At this point,
|
||||
* r4 (access) is re-useable, we use it for the new HPTE flags
|
||||
*/
|
||||
|
||||
/* Load the hidx index */
|
||||
rldicl r25,r3,64-12,60
|
||||
|
||||
/* Calc va and put it in r29 */
|
||||
rldicr r29,r5,28,63-28 /* r29 = (vsid << 28) */
|
||||
rldicl r3,r3,0,36 /* r3 = (ea & 0x0fffffff) */
|
||||
or r29,r3,r29 /* r29 = va
|
||||
|
||||
/* Calculate hash value for primary slot and store it in r28 */
|
||||
rldicl r5,r5,0,25 /* vsid & 0x0000007fffffffff */
|
||||
rldicl r0,r3,64-12,48 /* (ea >> 12) & 0xffff */
|
||||
xor r28,r5,r0
|
||||
|
||||
/* Convert linux PTE bits into HW equivalents */
|
||||
andi. r3,r30,0x1fe /* Get basic set of flags */
|
||||
xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */
|
||||
rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
|
||||
rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */
|
||||
and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
|
||||
andc r0,r30,r0 /* r0 = pte & ~r0 */
|
||||
rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */
|
||||
|
||||
/* We eventually do the icache sync here (maybe inline that
|
||||
* code rather than call a C function...)
|
||||
*/
|
||||
BEGIN_FTR_SECTION
|
||||
mr r4,r30
|
||||
mr r5,r7
|
||||
bl .hash_page_do_lazy_icache
|
||||
END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
|
||||
|
||||
/* At this point, r3 contains new PP bits, save them in
|
||||
* place of "access" in the param area (sic)
|
||||
*/
|
||||
std r3,STK_PARM(r4)(r1)
|
||||
|
||||
/* Get htab_hash_mask */
|
||||
ld r4,htab_hash_mask@got(2)
|
||||
ld r27,0(r4) /* htab_hash_mask -> r27 */
|
||||
|
||||
/* Check if we may already be in the hashtable, in this case, we
|
||||
* go to out-of-line code to try to modify the HPTE. We look for
|
||||
* the bit at (1 >> (index + 32))
|
||||
*/
|
||||
andi. r0,r31,_PAGE_HASHPTE
|
||||
li r26,0 /* Default hidx */
|
||||
beq htab_insert_pte
|
||||
ld r6,STK_PARM(r6)(r1)
|
||||
ori r26,r6,0x8000 /* Load the hidx mask */
|
||||
ld r26,0(r26)
|
||||
addi r5,r25,36 /* Check actual HPTE_SUB bit, this */
|
||||
rldcr. r0,r31,r5,0 /* must match pgtable.h definition */
|
||||
bne htab_modify_pte
|
||||
|
||||
htab_insert_pte:
|
||||
/* real page number in r5, PTE RPN value + index */
|
||||
rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
|
||||
sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT
|
||||
add r5,r5,r25
|
||||
sldi r5,r5,HW_PAGE_SHIFT
|
||||
|
||||
/* Calculate primary group hash */
|
||||
and r0,r28,r27
|
||||
rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
|
||||
|
||||
/* Call ppc_md.hpte_insert */
|
||||
ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */
|
||||
mr r4,r29 /* Retreive va */
|
||||
li r7,0 /* !bolted, !secondary */
|
||||
li r8,MMU_PAGE_4K /* page size */
|
||||
_GLOBAL(htab_call_hpte_insert1)
|
||||
bl . /* patched by htab_finish_init() */
|
||||
cmpdi 0,r3,0
|
||||
bge htab_pte_insert_ok /* Insertion successful */
|
||||
cmpdi 0,r3,-2 /* Critical failure */
|
||||
beq- htab_pte_insert_failure
|
||||
|
||||
/* Now try secondary slot */
|
||||
|
||||
/* real page number in r5, PTE RPN value + index */
|
||||
rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
|
||||
sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT
|
||||
add r5,r5,r25
|
||||
sldi r5,r5,HW_PAGE_SHIFT
|
||||
|
||||
/* Calculate secondary group hash */
|
||||
andc r0,r27,r28
|
||||
rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */
|
||||
|
||||
/* Call ppc_md.hpte_insert */
|
||||
ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */
|
||||
mr r4,r29 /* Retreive va */
|
||||
li r7,HPTE_V_SECONDARY /* !bolted, secondary */
|
||||
li r8,MMU_PAGE_4K /* page size */
|
||||
_GLOBAL(htab_call_hpte_insert2)
|
||||
bl . /* patched by htab_finish_init() */
|
||||
cmpdi 0,r3,0
|
||||
bge+ htab_pte_insert_ok /* Insertion successful */
|
||||
cmpdi 0,r3,-2 /* Critical failure */
|
||||
beq- htab_pte_insert_failure
|
||||
|
||||
/* Both are full, we need to evict something */
|
||||
mftb r0
|
||||
/* Pick a random group based on TB */
|
||||
andi. r0,r0,1
|
||||
mr r5,r28
|
||||
bne 2f
|
||||
not r5,r5
|
||||
2: and r0,r5,r27
|
||||
rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
|
||||
/* Call ppc_md.hpte_remove */
|
||||
_GLOBAL(htab_call_hpte_remove)
|
||||
bl . /* patched by htab_finish_init() */
|
||||
|
||||
/* Try all again */
|
||||
b htab_insert_pte
|
||||
|
||||
htab_bail_ok:
|
||||
li r3,0
|
||||
b htab_bail
|
||||
|
||||
htab_pte_insert_ok:
|
||||
/* Insert slot number & secondary bit in PTE second half,
|
||||
* clear _PAGE_BUSY and set approriate HPTE slot bit
|
||||
*/
|
||||
ld r6,STK_PARM(r6)(r1)
|
||||
li r0,_PAGE_BUSY
|
||||
andc r30,r30,r0
|
||||
/* HPTE SUB bit */
|
||||
li r0,1
|
||||
subfic r5,r25,27 /* Must match bit position in */
|
||||
sld r0,r0,r5 /* pgtable.h */
|
||||
or r30,r30,r0
|
||||
/* hindx */
|
||||
sldi r5,r25,2
|
||||
sld r3,r3,r5
|
||||
li r4,0xf
|
||||
sld r4,r4,r5
|
||||
andc r26,r26,r4
|
||||
or r26,r26,r3
|
||||
ori r5,r6,0x8000
|
||||
std r26,0(r5)
|
||||
lwsync
|
||||
std r30,0(r6)
|
||||
li r3, 0
|
||||
htab_bail:
|
||||
ld r25,STK_REG(r25)(r1)
|
||||
ld r26,STK_REG(r26)(r1)
|
||||
ld r27,STK_REG(r27)(r1)
|
||||
ld r28,STK_REG(r28)(r1)
|
||||
ld r29,STK_REG(r29)(r1)
|
||||
ld r30,STK_REG(r30)(r1)
|
||||
ld r31,STK_REG(r31)(r1)
|
||||
addi r1,r1,STACKFRAMESIZE
|
||||
ld r0,16(r1)
|
||||
mtlr r0
|
||||
blr
|
||||
|
||||
htab_modify_pte:
|
||||
/* Keep PP bits in r4 and slot idx from the PTE around in r3 */
|
||||
mr r4,r3
|
||||
sldi r5,r25,2
|
||||
srd r3,r26,r5
|
||||
|
||||
/* Secondary group ? if yes, get a inverted hash value */
|
||||
mr r5,r28
|
||||
andi. r0,r3,0x8 /* page secondary ? */
|
||||
beq 1f
|
||||
not r5,r5
|
||||
1: andi. r3,r3,0x7 /* extract idx alone */
|
||||
|
||||
/* Calculate proper slot value for ppc_md.hpte_updatepp */
|
||||
and r0,r5,r27
|
||||
rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */
|
||||
add r3,r0,r3 /* add slot idx */
|
||||
|
||||
/* Call ppc_md.hpte_updatepp */
|
||||
mr r5,r29 /* va */
|
||||
li r6,MMU_PAGE_4K /* page size */
|
||||
ld r7,STK_PARM(r8)(r1) /* get "local" param */
|
||||
_GLOBAL(htab_call_hpte_updatepp)
|
||||
bl . /* patched by htab_finish_init() */
|
||||
|
||||
/* if we failed because typically the HPTE wasn't really here
|
||||
* we try an insertion.
|
||||
*/
|
||||
cmpdi 0,r3,-1
|
||||
beq- htab_insert_pte
|
||||
|
||||
/* Clear the BUSY bit and Write out the PTE */
|
||||
li r0,_PAGE_BUSY
|
||||
andc r30,r30,r0
|
||||
ld r6,STK_PARM(r6)(r1)
|
||||
std r30,0(r6)
|
||||
li r3,0
|
||||
b htab_bail
|
||||
|
||||
htab_wrong_access:
|
||||
/* Bail out clearing reservation */
|
||||
stdcx. r31,0,r6
|
||||
li r3,1
|
||||
b htab_bail
|
||||
|
||||
htab_pte_insert_failure:
|
||||
/* Bail out restoring old PTE */
|
||||
ld r6,STK_PARM(r6)(r1)
|
||||
std r31,0(r6)
|
||||
li r3,-1
|
||||
b htab_bail
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* 64K SW & 64K HW in a 64K segment pages implementation *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
_GLOBAL(__hash_page_64K)
|
||||
mflr r0
|
||||
std r0,16(r1)
|
||||
stdu r1,-STACKFRAMESIZE(r1)
|
||||
/* Save all params that we need after a function call */
|
||||
std r6,STK_PARM(r6)(r1)
|
||||
std r8,STK_PARM(r8)(r1)
|
||||
|
||||
/* Add _PAGE_PRESENT to access */
|
||||
ori r4,r4,_PAGE_PRESENT
|
||||
|
||||
/* Save non-volatile registers.
|
||||
* r31 will hold "old PTE"
|
||||
* r30 is "new PTE"
|
||||
* r29 is "va"
|
||||
* r28 is a hash value
|
||||
* r27 is hashtab mask (maybe dynamic patched instead ?)
|
||||
*/
|
||||
std r27,STK_REG(r27)(r1)
|
||||
std r28,STK_REG(r28)(r1)
|
||||
std r29,STK_REG(r29)(r1)
|
||||
std r30,STK_REG(r30)(r1)
|
||||
std r31,STK_REG(r31)(r1)
|
||||
|
||||
/* Step 1:
|
||||
*
|
||||
* Check permissions, atomically mark the linux PTE busy
|
||||
* and hashed.
|
||||
*/
|
||||
1:
|
||||
ldarx r31,0,r6
|
||||
/* Check access rights (access & ~(pte_val(*ptep))) */
|
||||
andc. r0,r4,r31
|
||||
bne- ht64_wrong_access
|
||||
/* Check if PTE is busy */
|
||||
andi. r0,r31,_PAGE_BUSY
|
||||
/* If so, just bail out and refault if needed. Someone else
|
||||
* is changing this PTE anyway and might hash it.
|
||||
*/
|
||||
bne- ht64_bail_ok
|
||||
/* Prepare new PTE value (turn access RW into DIRTY, then
|
||||
* add BUSY,HASHPTE and ACCESSED)
|
||||
*/
|
||||
rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */
|
||||
or r30,r30,r31
|
||||
ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE
|
||||
/* Write the linux PTE atomically (setting busy) */
|
||||
stdcx. r30,0,r6
|
||||
bne- 1b
|
||||
isync
|
||||
|
||||
/* Step 2:
|
||||
*
|
||||
* Insert/Update the HPTE in the hash table. At this point,
|
||||
* r4 (access) is re-useable, we use it for the new HPTE flags
|
||||
*/
|
||||
|
||||
/* Calc va and put it in r29 */
|
||||
rldicr r29,r5,28,63-28
|
||||
rldicl r3,r3,0,36
|
||||
or r29,r3,r29
|
||||
|
||||
/* Calculate hash value for primary slot and store it in r28 */
|
||||
rldicl r5,r5,0,25 /* vsid & 0x0000007fffffffff */
|
||||
rldicl r0,r3,64-16,52 /* (ea >> 16) & 0xfff */
|
||||
xor r28,r5,r0
|
||||
|
||||
/* Convert linux PTE bits into HW equivalents */
|
||||
andi. r3,r30,0x1fe /* Get basic set of flags */
|
||||
xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */
|
||||
rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
|
||||
rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */
|
||||
and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
|
||||
andc r0,r30,r0 /* r0 = pte & ~r0 */
|
||||
rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */
|
||||
|
||||
/* We eventually do the icache sync here (maybe inline that
|
||||
* code rather than call a C function...)
|
||||
*/
|
||||
BEGIN_FTR_SECTION
|
||||
mr r4,r30
|
||||
mr r5,r7
|
||||
bl .hash_page_do_lazy_icache
|
||||
END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
|
||||
|
||||
/* At this point, r3 contains new PP bits, save them in
|
||||
* place of "access" in the param area (sic)
|
||||
*/
|
||||
std r3,STK_PARM(r4)(r1)
|
||||
|
||||
/* Get htab_hash_mask */
|
||||
ld r4,htab_hash_mask@got(2)
|
||||
ld r27,0(r4) /* htab_hash_mask -> r27 */
|
||||
|
||||
/* Check if we may already be in the hashtable, in this case, we
|
||||
* go to out-of-line code to try to modify the HPTE
|
||||
*/
|
||||
andi. r0,r31,_PAGE_HASHPTE
|
||||
bne ht64_modify_pte
|
||||
|
||||
ht64_insert_pte:
|
||||
/* Clear hpte bits in new pte (we also clear BUSY btw) and
|
||||
* add _PAGE_HASHPTE
|
||||
*/
|
||||
lis r0,_PAGE_HPTEFLAGS@h
|
||||
ori r0,r0,_PAGE_HPTEFLAGS@l
|
||||
andc r30,r30,r0
|
||||
ori r30,r30,_PAGE_HASHPTE
|
||||
|
||||
/* Phyical address in r5 */
|
||||
rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
|
||||
sldi r5,r5,PAGE_SHIFT
|
||||
|
||||
/* Calculate primary group hash */
|
||||
and r0,r28,r27
|
||||
rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
|
||||
|
||||
/* Call ppc_md.hpte_insert */
|
||||
ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */
|
||||
mr r4,r29 /* Retreive va */
|
||||
li r7,0 /* !bolted, !secondary */
|
||||
li r8,MMU_PAGE_64K
|
||||
_GLOBAL(ht64_call_hpte_insert1)
|
||||
bl . /* patched by htab_finish_init() */
|
||||
cmpdi 0,r3,0
|
||||
bge ht64_pte_insert_ok /* Insertion successful */
|
||||
cmpdi 0,r3,-2 /* Critical failure */
|
||||
beq- ht64_pte_insert_failure
|
||||
|
||||
/* Now try secondary slot */
|
||||
|
||||
/* Phyical address in r5 */
|
||||
rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
|
||||
sldi r5,r5,PAGE_SHIFT
|
||||
|
||||
/* Calculate secondary group hash */
|
||||
andc r0,r27,r28
|
||||
rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */
|
||||
|
||||
/* Call ppc_md.hpte_insert */
|
||||
ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */
|
||||
mr r4,r29 /* Retreive va */
|
||||
li r7,HPTE_V_SECONDARY /* !bolted, secondary */
|
||||
li r8,MMU_PAGE_64K
|
||||
_GLOBAL(ht64_call_hpte_insert2)
|
||||
bl . /* patched by htab_finish_init() */
|
||||
cmpdi 0,r3,0
|
||||
bge+ ht64_pte_insert_ok /* Insertion successful */
|
||||
cmpdi 0,r3,-2 /* Critical failure */
|
||||
beq- ht64_pte_insert_failure
|
||||
|
||||
/* Both are full, we need to evict something */
|
||||
mftb r0
|
||||
/* Pick a random group based on TB */
|
||||
andi. r0,r0,1
|
||||
mr r5,r28
|
||||
bne 2f
|
||||
not r5,r5
|
||||
2: and r0,r5,r27
|
||||
rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
|
||||
/* Call ppc_md.hpte_remove */
|
||||
_GLOBAL(ht64_call_hpte_remove)
|
||||
bl . /* patched by htab_finish_init() */
|
||||
|
||||
/* Try all again */
|
||||
b ht64_insert_pte
|
||||
|
||||
ht64_bail_ok:
|
||||
li r3,0
|
||||
b ht64_bail
|
||||
|
||||
ht64_pte_insert_ok:
|
||||
/* Insert slot number & secondary bit in PTE */
|
||||
rldimi r30,r3,12,63-15
|
||||
|
||||
/* Write out the PTE with a normal write
|
||||
* (maybe add eieio may be good still ?)
|
||||
*/
|
||||
ht64_write_out_pte:
|
||||
ld r6,STK_PARM(r6)(r1)
|
||||
std r30,0(r6)
|
||||
li r3, 0
|
||||
ht64_bail:
|
||||
ld r27,STK_REG(r27)(r1)
|
||||
ld r28,STK_REG(r28)(r1)
|
||||
ld r29,STK_REG(r29)(r1)
|
||||
ld r30,STK_REG(r30)(r1)
|
||||
ld r31,STK_REG(r31)(r1)
|
||||
addi r1,r1,STACKFRAMESIZE
|
||||
ld r0,16(r1)
|
||||
mtlr r0
|
||||
blr
|
||||
|
||||
ht64_modify_pte:
|
||||
/* Keep PP bits in r4 and slot idx from the PTE around in r3 */
|
||||
mr r4,r3
|
||||
rlwinm r3,r31,32-12,29,31
|
||||
|
||||
/* Secondary group ? if yes, get a inverted hash value */
|
||||
mr r5,r28
|
||||
andi. r0,r31,_PAGE_F_SECOND
|
||||
beq 1f
|
||||
not r5,r5
|
||||
1:
|
||||
/* Calculate proper slot value for ppc_md.hpte_updatepp */
|
||||
and r0,r5,r27
|
||||
rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */
|
||||
add r3,r0,r3 /* add slot idx */
|
||||
|
||||
/* Call ppc_md.hpte_updatepp */
|
||||
mr r5,r29 /* va */
|
||||
li r6,MMU_PAGE_64K
|
||||
ld r7,STK_PARM(r8)(r1) /* get "local" param */
|
||||
_GLOBAL(ht64_call_hpte_updatepp)
|
||||
bl . /* patched by htab_finish_init() */
|
||||
|
||||
/* if we failed because typically the HPTE wasn't really here
|
||||
* we try an insertion.
|
||||
*/
|
||||
cmpdi 0,r3,-1
|
||||
beq- ht64_insert_pte
|
||||
|
||||
/* Clear the BUSY bit and Write out the PTE */
|
||||
li r0,_PAGE_BUSY
|
||||
andc r30,r30,r0
|
||||
b ht64_write_out_pte
|
||||
|
||||
ht64_wrong_access:
|
||||
/* Bail out clearing reservation */
|
||||
stdcx. r31,0,r6
|
||||
li r3,1
|
||||
b ht64_bail
|
||||
|
||||
ht64_pte_insert_failure:
|
||||
/* Bail out restoring old PTE */
|
||||
ld r6,STK_PARM(r6)(r1)
|
||||
std r31,0(r6)
|
||||
li r3,-1
|
||||
b ht64_bail
|
||||
|
||||
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* Huge pages implementation is in hugetlbpage.c *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#undef DEBUG_LOW
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/threads.h>
|
||||
|
@ -22,11 +25,84 @@
|
|||
#include <asm/tlbflush.h>
|
||||
#include <asm/tlb.h>
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/udbg.h>
|
||||
|
||||
#ifdef DEBUG_LOW
|
||||
#define DBG_LOW(fmt...) udbg_printf(fmt)
|
||||
#else
|
||||
#define DBG_LOW(fmt...)
|
||||
#endif
|
||||
|
||||
#define HPTE_LOCK_BIT 3
|
||||
|
||||
static DEFINE_SPINLOCK(native_tlbie_lock);
|
||||
|
||||
static inline void __tlbie(unsigned long va, unsigned int psize)
|
||||
{
|
||||
unsigned int penc;
|
||||
|
||||
/* clear top 16 bits, non SLS segment */
|
||||
va &= ~(0xffffULL << 48);
|
||||
|
||||
switch (psize) {
|
||||
case MMU_PAGE_4K:
|
||||
va &= ~0xffful;
|
||||
asm volatile("tlbie %0,0" : : "r" (va) : "memory");
|
||||
break;
|
||||
default:
|
||||
penc = mmu_psize_defs[psize].penc;
|
||||
va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
|
||||
va |= (0x7f >> (8 - penc)) << 12;
|
||||
asm volatile("tlbie %0,1" : : "r" (va) : "memory");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __tlbiel(unsigned long va, unsigned int psize)
|
||||
{
|
||||
unsigned int penc;
|
||||
|
||||
/* clear top 16 bits, non SLS segment */
|
||||
va &= ~(0xffffULL << 48);
|
||||
|
||||
switch (psize) {
|
||||
case MMU_PAGE_4K:
|
||||
va &= ~0xffful;
|
||||
asm volatile(".long 0x7c000224 | (%0 << 11) | (0 << 21)"
|
||||
: : "r"(va) : "memory");
|
||||
break;
|
||||
default:
|
||||
penc = mmu_psize_defs[psize].penc;
|
||||
va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
|
||||
va |= (0x7f >> (8 - penc)) << 12;
|
||||
asm volatile(".long 0x7c000224 | (%0 << 11) | (1 << 21)"
|
||||
: : "r"(va) : "memory");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static inline void tlbie(unsigned long va, int psize, int local)
|
||||
{
|
||||
unsigned int use_local = local && cpu_has_feature(CPU_FTR_TLBIEL);
|
||||
int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
|
||||
|
||||
if (use_local)
|
||||
use_local = mmu_psize_defs[psize].tlbiel;
|
||||
if (lock_tlbie && !use_local)
|
||||
spin_lock(&native_tlbie_lock);
|
||||
asm volatile("ptesync": : :"memory");
|
||||
if (use_local) {
|
||||
__tlbiel(va, psize);
|
||||
asm volatile("ptesync": : :"memory");
|
||||
} else {
|
||||
__tlbie(va, psize);
|
||||
asm volatile("eieio; tlbsync; ptesync": : :"memory");
|
||||
}
|
||||
if (lock_tlbie && !use_local)
|
||||
spin_unlock(&native_tlbie_lock);
|
||||
}
|
||||
|
||||
static inline void native_lock_hpte(hpte_t *hptep)
|
||||
{
|
||||
unsigned long *word = &hptep->v;
|
||||
|
@ -48,13 +124,19 @@ static inline void native_unlock_hpte(hpte_t *hptep)
|
|||
}
|
||||
|
||||
long native_hpte_insert(unsigned long hpte_group, unsigned long va,
|
||||
unsigned long prpn, unsigned long vflags,
|
||||
unsigned long rflags)
|
||||
unsigned long pa, unsigned long rflags,
|
||||
unsigned long vflags, int psize)
|
||||
{
|
||||
hpte_t *hptep = htab_address + hpte_group;
|
||||
unsigned long hpte_v, hpte_r;
|
||||
int i;
|
||||
|
||||
if (!(vflags & HPTE_V_BOLTED)) {
|
||||
DBG_LOW(" insert(group=%lx, va=%016lx, pa=%016lx,"
|
||||
" rflags=%lx, vflags=%lx, psize=%d)\n",
|
||||
hpte_group, va, pa, rflags, vflags, psize);
|
||||
}
|
||||
|
||||
for (i = 0; i < HPTES_PER_GROUP; i++) {
|
||||
if (! (hptep->v & HPTE_V_VALID)) {
|
||||
/* retry with lock held */
|
||||
|
@ -70,10 +152,13 @@ long native_hpte_insert(unsigned long hpte_group, unsigned long va,
|
|||
if (i == HPTES_PER_GROUP)
|
||||
return -1;
|
||||
|
||||
hpte_v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID;
|
||||
if (vflags & HPTE_V_LARGE)
|
||||
va &= ~(1UL << HPTE_V_AVPN_SHIFT);
|
||||
hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags;
|
||||
hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID;
|
||||
hpte_r = hpte_encode_r(pa, psize) | rflags;
|
||||
|
||||
if (!(vflags & HPTE_V_BOLTED)) {
|
||||
DBG_LOW(" i=%x hpte_v=%016lx, hpte_r=%016lx\n",
|
||||
i, hpte_v, hpte_r);
|
||||
}
|
||||
|
||||
hptep->r = hpte_r;
|
||||
/* Guarantee the second dword is visible before the valid bit */
|
||||
|
@ -96,6 +181,8 @@ static long native_hpte_remove(unsigned long hpte_group)
|
|||
int slot_offset;
|
||||
unsigned long hpte_v;
|
||||
|
||||
DBG_LOW(" remove(group=%lx)\n", hpte_group);
|
||||
|
||||
/* pick a random entry to start at */
|
||||
slot_offset = mftb() & 0x7;
|
||||
|
||||
|
@ -126,34 +213,51 @@ static long native_hpte_remove(unsigned long hpte_group)
|
|||
return i;
|
||||
}
|
||||
|
||||
static inline void set_pp_bit(unsigned long pp, hpte_t *addr)
|
||||
static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
|
||||
unsigned long va, int psize, int local)
|
||||
{
|
||||
unsigned long old;
|
||||
unsigned long *p = &addr->r;
|
||||
hpte_t *hptep = htab_address + slot;
|
||||
unsigned long hpte_v, want_v;
|
||||
int ret = 0;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldarx %0,0,%3\n\
|
||||
rldimi %0,%2,0,61\n\
|
||||
stdcx. %0,0,%3\n\
|
||||
bne 1b"
|
||||
: "=&r" (old), "=m" (*p)
|
||||
: "r" (pp), "r" (p), "m" (*p)
|
||||
: "cc");
|
||||
want_v = hpte_encode_v(va, psize);
|
||||
|
||||
DBG_LOW(" update(va=%016lx, avpnv=%016lx, hash=%016lx, newpp=%x)",
|
||||
va, want_v & HPTE_V_AVPN, slot, newpp);
|
||||
|
||||
native_lock_hpte(hptep);
|
||||
|
||||
hpte_v = hptep->v;
|
||||
|
||||
/* Even if we miss, we need to invalidate the TLB */
|
||||
if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) {
|
||||
DBG_LOW(" -> miss\n");
|
||||
native_unlock_hpte(hptep);
|
||||
ret = -1;
|
||||
} else {
|
||||
DBG_LOW(" -> hit\n");
|
||||
/* Update the HPTE */
|
||||
hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) |
|
||||
(newpp & (HPTE_R_PP | HPTE_R_N));
|
||||
native_unlock_hpte(hptep);
|
||||
}
|
||||
|
||||
/* Ensure it is out of the tlb too. */
|
||||
tlbie(va, psize, local);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only works on small pages. Yes its ugly to have to check each slot in
|
||||
* the group but we only use this during bootup.
|
||||
*/
|
||||
static long native_hpte_find(unsigned long vpn)
|
||||
static long native_hpte_find(unsigned long va, int psize)
|
||||
{
|
||||
hpte_t *hptep;
|
||||
unsigned long hash;
|
||||
unsigned long i, j;
|
||||
long slot;
|
||||
unsigned long hpte_v;
|
||||
unsigned long want_v, hpte_v;
|
||||
|
||||
hash = hpt_hash(vpn, 0);
|
||||
hash = hpt_hash(va, mmu_psize_defs[psize].shift);
|
||||
want_v = hpte_encode_v(va, psize);
|
||||
|
||||
for (j = 0; j < 2; j++) {
|
||||
slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
|
||||
|
@ -161,7 +265,7 @@ static long native_hpte_find(unsigned long vpn)
|
|||
hptep = htab_address + slot;
|
||||
hpte_v = hptep->v;
|
||||
|
||||
if ((HPTE_V_AVPN_VAL(hpte_v) == (vpn >> 11))
|
||||
if (HPTE_V_COMPARE(hpte_v, want_v)
|
||||
&& (hpte_v & HPTE_V_VALID)
|
||||
&& ( !!(hpte_v & HPTE_V_SECONDARY) == j)) {
|
||||
/* HPTE matches */
|
||||
|
@ -177,118 +281,90 @@ static long native_hpte_find(unsigned long vpn)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
|
||||
unsigned long va, int large, int local)
|
||||
{
|
||||
hpte_t *hptep = htab_address + slot;
|
||||
unsigned long hpte_v;
|
||||
unsigned long avpn = va >> 23;
|
||||
int ret = 0;
|
||||
|
||||
if (large)
|
||||
avpn &= ~1;
|
||||
|
||||
native_lock_hpte(hptep);
|
||||
|
||||
hpte_v = hptep->v;
|
||||
|
||||
/* Even if we miss, we need to invalidate the TLB */
|
||||
if ((HPTE_V_AVPN_VAL(hpte_v) != avpn)
|
||||
|| !(hpte_v & HPTE_V_VALID)) {
|
||||
native_unlock_hpte(hptep);
|
||||
ret = -1;
|
||||
} else {
|
||||
set_pp_bit(newpp, hptep);
|
||||
native_unlock_hpte(hptep);
|
||||
}
|
||||
|
||||
/* Ensure it is out of the tlb too */
|
||||
if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
|
||||
tlbiel(va);
|
||||
} else {
|
||||
int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
|
||||
|
||||
if (lock_tlbie)
|
||||
spin_lock(&native_tlbie_lock);
|
||||
tlbie(va, large);
|
||||
if (lock_tlbie)
|
||||
spin_unlock(&native_tlbie_lock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* Does not work on large pages.
|
||||
*
|
||||
* No need to lock here because we should be the only user.
|
||||
*/
|
||||
static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea)
|
||||
static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
|
||||
int psize)
|
||||
{
|
||||
unsigned long vsid, va, vpn, flags = 0;
|
||||
unsigned long vsid, va;
|
||||
long slot;
|
||||
hpte_t *hptep;
|
||||
int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
|
||||
|
||||
vsid = get_kernel_vsid(ea);
|
||||
va = (vsid << 28) | (ea & 0x0fffffff);
|
||||
vpn = va >> PAGE_SHIFT;
|
||||
|
||||
slot = native_hpte_find(vpn);
|
||||
slot = native_hpte_find(va, psize);
|
||||
if (slot == -1)
|
||||
panic("could not find page to bolt\n");
|
||||
hptep = htab_address + slot;
|
||||
|
||||
set_pp_bit(newpp, hptep);
|
||||
/* Update the HPTE */
|
||||
hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) |
|
||||
(newpp & (HPTE_R_PP | HPTE_R_N));
|
||||
|
||||
/* Ensure it is out of the tlb too */
|
||||
if (lock_tlbie)
|
||||
spin_lock_irqsave(&native_tlbie_lock, flags);
|
||||
tlbie(va, 0);
|
||||
if (lock_tlbie)
|
||||
spin_unlock_irqrestore(&native_tlbie_lock, flags);
|
||||
/* Ensure it is out of the tlb too. */
|
||||
tlbie(va, psize, 0);
|
||||
}
|
||||
|
||||
static void native_hpte_invalidate(unsigned long slot, unsigned long va,
|
||||
int large, int local)
|
||||
int psize, int local)
|
||||
{
|
||||
hpte_t *hptep = htab_address + slot;
|
||||
unsigned long hpte_v;
|
||||
unsigned long avpn = va >> 23;
|
||||
unsigned long want_v;
|
||||
unsigned long flags;
|
||||
int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
|
||||
|
||||
if (large)
|
||||
avpn &= ~1;
|
||||
|
||||
local_irq_save(flags);
|
||||
native_lock_hpte(hptep);
|
||||
|
||||
DBG_LOW(" invalidate(va=%016lx, hash: %x)\n", va, slot);
|
||||
|
||||
want_v = hpte_encode_v(va, psize);
|
||||
native_lock_hpte(hptep);
|
||||
hpte_v = hptep->v;
|
||||
|
||||
/* Even if we miss, we need to invalidate the TLB */
|
||||
if ((HPTE_V_AVPN_VAL(hpte_v) != avpn)
|
||||
|| !(hpte_v & HPTE_V_VALID)) {
|
||||
if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID))
|
||||
native_unlock_hpte(hptep);
|
||||
} else {
|
||||
else
|
||||
/* Invalidate the hpte. NOTE: this also unlocks it */
|
||||
hptep->v = 0;
|
||||
|
||||
/* Invalidate the TLB */
|
||||
tlbie(va, psize, local);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX This need fixing based on page size. It's only used by
|
||||
* native_hpte_clear() for now which needs fixing too so they
|
||||
* make a good pair...
|
||||
*/
|
||||
static unsigned long slot2va(unsigned long hpte_v, unsigned long slot)
|
||||
{
|
||||
unsigned long avpn = HPTE_V_AVPN_VAL(hpte_v);
|
||||
unsigned long va;
|
||||
|
||||
va = avpn << 23;
|
||||
|
||||
if (! (hpte_v & HPTE_V_LARGE)) {
|
||||
unsigned long vpi, pteg;
|
||||
|
||||
pteg = slot / HPTES_PER_GROUP;
|
||||
if (hpte_v & HPTE_V_SECONDARY)
|
||||
pteg = ~pteg;
|
||||
|
||||
vpi = ((va >> 28) ^ pteg) & htab_hash_mask;
|
||||
|
||||
va |= vpi << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
/* Invalidate the tlb */
|
||||
if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
|
||||
tlbiel(va);
|
||||
} else {
|
||||
if (lock_tlbie)
|
||||
spin_lock(&native_tlbie_lock);
|
||||
tlbie(va, large);
|
||||
if (lock_tlbie)
|
||||
spin_unlock(&native_tlbie_lock);
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
return va;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -298,6 +374,8 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
|
|||
*
|
||||
* TODO: add batching support when enabled. remember, no dynamic memory here,
|
||||
* athough there is the control page available...
|
||||
*
|
||||
* XXX FIXME: 4k only for now !
|
||||
*/
|
||||
static void native_hpte_clear(void)
|
||||
{
|
||||
|
@ -327,7 +405,7 @@ static void native_hpte_clear(void)
|
|||
|
||||
if (hpte_v & HPTE_V_VALID) {
|
||||
hptep->v = 0;
|
||||
tlbie(slot2va(hpte_v, slot), hpte_v & HPTE_V_LARGE);
|
||||
tlbie(slot2va(hpte_v, slot), MMU_PAGE_4K, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,59 +413,59 @@ static void native_hpte_clear(void)
|
|||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Batched hash table flush, we batch the tlbie's to avoid taking/releasing
|
||||
* the lock all the time
|
||||
*/
|
||||
static void native_flush_hash_range(unsigned long number, int local)
|
||||
{
|
||||
unsigned long va, vpn, hash, secondary, slot, flags, avpn;
|
||||
int i, j;
|
||||
unsigned long va, hash, index, hidx, shift, slot;
|
||||
hpte_t *hptep;
|
||||
unsigned long hpte_v;
|
||||
unsigned long want_v;
|
||||
unsigned long flags;
|
||||
real_pte_t pte;
|
||||
struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
|
||||
unsigned long large = batch->large;
|
||||
unsigned long psize = batch->psize;
|
||||
int i;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i < number; i++) {
|
||||
va = batch->vaddr[j];
|
||||
if (large)
|
||||
vpn = va >> HPAGE_SHIFT;
|
||||
else
|
||||
vpn = va >> PAGE_SHIFT;
|
||||
hash = hpt_hash(vpn, large);
|
||||
secondary = (pte_val(batch->pte[i]) & _PAGE_SECONDARY) >> 15;
|
||||
if (secondary)
|
||||
hash = ~hash;
|
||||
slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
|
||||
slot += (pte_val(batch->pte[i]) & _PAGE_GROUP_IX) >> 12;
|
||||
va = batch->vaddr[i];
|
||||
pte = batch->pte[i];
|
||||
|
||||
hptep = htab_address + slot;
|
||||
|
||||
avpn = va >> 23;
|
||||
if (large)
|
||||
avpn &= ~0x1UL;
|
||||
|
||||
native_lock_hpte(hptep);
|
||||
|
||||
hpte_v = hptep->v;
|
||||
|
||||
/* Even if we miss, we need to invalidate the TLB */
|
||||
if ((HPTE_V_AVPN_VAL(hpte_v) != avpn)
|
||||
|| !(hpte_v & HPTE_V_VALID)) {
|
||||
native_unlock_hpte(hptep);
|
||||
} else {
|
||||
/* Invalidate the hpte. NOTE: this also unlocks it */
|
||||
hptep->v = 0;
|
||||
}
|
||||
|
||||
j++;
|
||||
pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
|
||||
hash = hpt_hash(va, shift);
|
||||
hidx = __rpte_to_hidx(pte, index);
|
||||
if (hidx & _PTEIDX_SECONDARY)
|
||||
hash = ~hash;
|
||||
slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
|
||||
slot += hidx & _PTEIDX_GROUP_IX;
|
||||
hptep = htab_address + slot;
|
||||
want_v = hpte_encode_v(va, psize);
|
||||
native_lock_hpte(hptep);
|
||||
hpte_v = hptep->v;
|
||||
if (!HPTE_V_COMPARE(hpte_v, want_v) ||
|
||||
!(hpte_v & HPTE_V_VALID))
|
||||
native_unlock_hpte(hptep);
|
||||
else
|
||||
hptep->v = 0;
|
||||
} pte_iterate_hashed_end();
|
||||
}
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
|
||||
if (cpu_has_feature(CPU_FTR_TLBIEL) &&
|
||||
mmu_psize_defs[psize].tlbiel && local) {
|
||||
asm volatile("ptesync":::"memory");
|
||||
for (i = 0; i < number; i++) {
|
||||
va = batch->vaddr[i];
|
||||
pte = batch->pte[i];
|
||||
|
||||
for (i = 0; i < j; i++)
|
||||
__tlbiel(batch->vaddr[i]);
|
||||
|
||||
pte_iterate_hashed_subpages(pte, psize, va, index,
|
||||
shift) {
|
||||
__tlbiel(va, psize);
|
||||
} pte_iterate_hashed_end();
|
||||
}
|
||||
asm volatile("ptesync":::"memory");
|
||||
} else {
|
||||
int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
|
||||
|
@ -396,10 +474,15 @@ static void native_flush_hash_range(unsigned long number, int local)
|
|||
spin_lock(&native_tlbie_lock);
|
||||
|
||||
asm volatile("ptesync":::"memory");
|
||||
for (i = 0; i < number; i++) {
|
||||
va = batch->vaddr[i];
|
||||
pte = batch->pte[i];
|
||||
|
||||
for (i = 0; i < j; i++)
|
||||
__tlbie(batch->vaddr[i], large);
|
||||
|
||||
pte_iterate_hashed_subpages(pte, psize, va, index,
|
||||
shift) {
|
||||
__tlbie(va, psize);
|
||||
} pte_iterate_hashed_end();
|
||||
}
|
||||
asm volatile("eieio; tlbsync; ptesync":::"memory");
|
||||
|
||||
if (lock_tlbie)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#undef DEBUG
|
||||
#undef DEBUG_LOW
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
@ -59,6 +60,15 @@
|
|||
#define DBG(fmt...)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_LOW
|
||||
#define DBG_LOW(fmt...) udbg_printf(fmt)
|
||||
#else
|
||||
#define DBG_LOW(fmt...)
|
||||
#endif
|
||||
|
||||
#define KB (1024)
|
||||
#define MB (1024*KB)
|
||||
|
||||
/*
|
||||
* Note: pte --> Linux PTE
|
||||
* HPTE --> PowerPC Hashed Page Table Entry
|
||||
|
@ -77,91 +87,290 @@ extern unsigned long dart_tablebase;
|
|||
|
||||
hpte_t *htab_address;
|
||||
unsigned long htab_hash_mask;
|
||||
|
||||
unsigned long _SDR1;
|
||||
struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
|
||||
int mmu_linear_psize = MMU_PAGE_4K;
|
||||
int mmu_virtual_psize = MMU_PAGE_4K;
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
int mmu_huge_psize = MMU_PAGE_16M;
|
||||
unsigned int HPAGE_SHIFT;
|
||||
#endif
|
||||
|
||||
#define KB (1024)
|
||||
#define MB (1024*KB)
|
||||
/* There are definitions of page sizes arrays to be used when none
|
||||
* is provided by the firmware.
|
||||
*/
|
||||
|
||||
static inline void loop_forever(void)
|
||||
/* Pre-POWER4 CPUs (4k pages only)
|
||||
*/
|
||||
struct mmu_psize_def mmu_psize_defaults_old[] = {
|
||||
[MMU_PAGE_4K] = {
|
||||
.shift = 12,
|
||||
.sllp = 0,
|
||||
.penc = 0,
|
||||
.avpnm = 0,
|
||||
.tlbiel = 0,
|
||||
},
|
||||
};
|
||||
|
||||
/* POWER4, GPUL, POWER5
|
||||
*
|
||||
* Support for 16Mb large pages
|
||||
*/
|
||||
struct mmu_psize_def mmu_psize_defaults_gp[] = {
|
||||
[MMU_PAGE_4K] = {
|
||||
.shift = 12,
|
||||
.sllp = 0,
|
||||
.penc = 0,
|
||||
.avpnm = 0,
|
||||
.tlbiel = 1,
|
||||
},
|
||||
[MMU_PAGE_16M] = {
|
||||
.shift = 24,
|
||||
.sllp = SLB_VSID_L,
|
||||
.penc = 0,
|
||||
.avpnm = 0x1UL,
|
||||
.tlbiel = 0,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
|
||||
unsigned long pstart, unsigned long mode, int psize)
|
||||
{
|
||||
volatile unsigned long x = 1;
|
||||
for(;x;x|=1)
|
||||
;
|
||||
}
|
||||
|
||||
static inline void create_pte_mapping(unsigned long start, unsigned long end,
|
||||
unsigned long mode, int large)
|
||||
{
|
||||
unsigned long addr;
|
||||
unsigned int step;
|
||||
unsigned long vaddr, paddr;
|
||||
unsigned int step, shift;
|
||||
unsigned long tmp_mode;
|
||||
unsigned long vflags;
|
||||
int ret = 0;
|
||||
|
||||
if (large) {
|
||||
step = 16*MB;
|
||||
vflags = HPTE_V_BOLTED | HPTE_V_LARGE;
|
||||
} else {
|
||||
step = 4*KB;
|
||||
vflags = HPTE_V_BOLTED;
|
||||
}
|
||||
shift = mmu_psize_defs[psize].shift;
|
||||
step = 1 << shift;
|
||||
|
||||
for (addr = start; addr < end; addr += step) {
|
||||
for (vaddr = vstart, paddr = pstart; vaddr < vend;
|
||||
vaddr += step, paddr += step) {
|
||||
unsigned long vpn, hash, hpteg;
|
||||
unsigned long vsid = get_kernel_vsid(addr);
|
||||
unsigned long va = (vsid << 28) | (addr & 0xfffffff);
|
||||
int ret = -1;
|
||||
|
||||
if (large)
|
||||
vpn = va >> HPAGE_SHIFT;
|
||||
else
|
||||
vpn = va >> PAGE_SHIFT;
|
||||
|
||||
unsigned long vsid = get_kernel_vsid(vaddr);
|
||||
unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff);
|
||||
|
||||
vpn = va >> shift;
|
||||
tmp_mode = mode;
|
||||
|
||||
/* Make non-kernel text non-executable */
|
||||
if (!in_kernel_text(addr))
|
||||
tmp_mode = mode | HW_NO_EXEC;
|
||||
|
||||
hash = hpt_hash(vpn, large);
|
||||
if (!in_kernel_text(vaddr))
|
||||
tmp_mode = mode | HPTE_R_N;
|
||||
|
||||
hash = hpt_hash(va, shift);
|
||||
hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
|
||||
|
||||
/* The crap below can be cleaned once ppd_md.probe() can
|
||||
* set up the hash callbacks, thus we can just used the
|
||||
* normal insert callback here.
|
||||
*/
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
if (systemcfg->platform & PLATFORM_ISERIES_LPAR)
|
||||
ret = iSeries_hpte_bolt_or_insert(hpteg, va,
|
||||
virt_to_abs(addr) >> PAGE_SHIFT,
|
||||
vflags, tmp_mode);
|
||||
if (systemcfg->platform == PLATFORM_ISERIES_LPAR)
|
||||
ret = iSeries_hpte_insert(hpteg, va,
|
||||
virt_to_abs(paddr),
|
||||
tmp_mode,
|
||||
HPTE_V_BOLTED,
|
||||
psize);
|
||||
else
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
if (systemcfg->platform & PLATFORM_LPAR)
|
||||
ret = pSeries_lpar_hpte_insert(hpteg, va,
|
||||
virt_to_abs(addr) >> PAGE_SHIFT,
|
||||
vflags, tmp_mode);
|
||||
virt_to_abs(paddr),
|
||||
tmp_mode,
|
||||
HPTE_V_BOLTED,
|
||||
psize);
|
||||
else
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_MULTIPLATFORM
|
||||
ret = native_hpte_insert(hpteg, va,
|
||||
virt_to_abs(addr) >> PAGE_SHIFT,
|
||||
vflags, tmp_mode);
|
||||
virt_to_abs(paddr),
|
||||
tmp_mode, HPTE_V_BOLTED,
|
||||
psize);
|
||||
#endif
|
||||
|
||||
if (ret == -1) {
|
||||
ppc64_terminate_msg(0x20, "create_pte_mapping");
|
||||
loop_forever();
|
||||
}
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
||||
static unsigned long get_hashtable_size(void)
|
||||
static int __init htab_dt_scan_page_sizes(unsigned long node,
|
||||
const char *uname, int depth,
|
||||
void *data)
|
||||
{
|
||||
char *type = of_get_flat_dt_prop(node, "device_type", NULL);
|
||||
u32 *prop;
|
||||
unsigned long size = 0;
|
||||
|
||||
/* We are scanning "cpu" nodes only */
|
||||
if (type == NULL || strcmp(type, "cpu") != 0)
|
||||
return 0;
|
||||
|
||||
prop = (u32 *)of_get_flat_dt_prop(node,
|
||||
"ibm,segment-page-sizes", &size);
|
||||
if (prop != NULL) {
|
||||
DBG("Page sizes from device-tree:\n");
|
||||
size /= 4;
|
||||
cur_cpu_spec->cpu_features &= ~(CPU_FTR_16M_PAGE);
|
||||
while(size > 0) {
|
||||
unsigned int shift = prop[0];
|
||||
unsigned int slbenc = prop[1];
|
||||
unsigned int lpnum = prop[2];
|
||||
unsigned int lpenc = 0;
|
||||
struct mmu_psize_def *def;
|
||||
int idx = -1;
|
||||
|
||||
size -= 3; prop += 3;
|
||||
while(size > 0 && lpnum) {
|
||||
if (prop[0] == shift)
|
||||
lpenc = prop[1];
|
||||
prop += 2; size -= 2;
|
||||
lpnum--;
|
||||
}
|
||||
switch(shift) {
|
||||
case 0xc:
|
||||
idx = MMU_PAGE_4K;
|
||||
break;
|
||||
case 0x10:
|
||||
idx = MMU_PAGE_64K;
|
||||
break;
|
||||
case 0x14:
|
||||
idx = MMU_PAGE_1M;
|
||||
break;
|
||||
case 0x18:
|
||||
idx = MMU_PAGE_16M;
|
||||
cur_cpu_spec->cpu_features |= CPU_FTR_16M_PAGE;
|
||||
break;
|
||||
case 0x22:
|
||||
idx = MMU_PAGE_16G;
|
||||
break;
|
||||
}
|
||||
if (idx < 0)
|
||||
continue;
|
||||
def = &mmu_psize_defs[idx];
|
||||
def->shift = shift;
|
||||
if (shift <= 23)
|
||||
def->avpnm = 0;
|
||||
else
|
||||
def->avpnm = (1 << (shift - 23)) - 1;
|
||||
def->sllp = slbenc;
|
||||
def->penc = lpenc;
|
||||
/* We don't know for sure what's up with tlbiel, so
|
||||
* for now we only set it for 4K and 64K pages
|
||||
*/
|
||||
if (idx == MMU_PAGE_4K || idx == MMU_PAGE_64K)
|
||||
def->tlbiel = 1;
|
||||
else
|
||||
def->tlbiel = 0;
|
||||
|
||||
DBG(" %d: shift=%02x, sllp=%04x, avpnm=%08x, "
|
||||
"tlbiel=%d, penc=%d\n",
|
||||
idx, shift, def->sllp, def->avpnm, def->tlbiel,
|
||||
def->penc);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void __init htab_init_page_sizes(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Default to 4K pages only */
|
||||
memcpy(mmu_psize_defs, mmu_psize_defaults_old,
|
||||
sizeof(mmu_psize_defaults_old));
|
||||
|
||||
/*
|
||||
* Try to find the available page sizes in the device-tree
|
||||
*/
|
||||
rc = of_scan_flat_dt(htab_dt_scan_page_sizes, NULL);
|
||||
if (rc != 0) /* Found */
|
||||
goto found;
|
||||
|
||||
/*
|
||||
* Not in the device-tree, let's fallback on known size
|
||||
* list for 16M capable GP & GR
|
||||
*/
|
||||
if ((systemcfg->platform != PLATFORM_ISERIES_LPAR) &&
|
||||
cpu_has_feature(CPU_FTR_16M_PAGE))
|
||||
memcpy(mmu_psize_defs, mmu_psize_defaults_gp,
|
||||
sizeof(mmu_psize_defaults_gp));
|
||||
found:
|
||||
/*
|
||||
* Pick a size for the linear mapping. Currently, we only support
|
||||
* 16M, 1M and 4K which is the default
|
||||
*/
|
||||
if (mmu_psize_defs[MMU_PAGE_16M].shift)
|
||||
mmu_linear_psize = MMU_PAGE_16M;
|
||||
else if (mmu_psize_defs[MMU_PAGE_1M].shift)
|
||||
mmu_linear_psize = MMU_PAGE_1M;
|
||||
|
||||
/*
|
||||
* Pick a size for the ordinary pages. Default is 4K, we support
|
||||
* 64K if cache inhibited large pages are supported by the
|
||||
* processor
|
||||
*/
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
if (mmu_psize_defs[MMU_PAGE_64K].shift &&
|
||||
cpu_has_feature(CPU_FTR_CI_LARGE_PAGE))
|
||||
mmu_virtual_psize = MMU_PAGE_64K;
|
||||
#endif
|
||||
|
||||
printk(KERN_INFO "Page orders: linear mapping = %d, others = %d\n",
|
||||
mmu_psize_defs[mmu_linear_psize].shift,
|
||||
mmu_psize_defs[mmu_virtual_psize].shift);
|
||||
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
/* Init large page size. Currently, we pick 16M or 1M depending
|
||||
* on what is available
|
||||
*/
|
||||
if (mmu_psize_defs[MMU_PAGE_16M].shift)
|
||||
mmu_huge_psize = MMU_PAGE_16M;
|
||||
else if (mmu_psize_defs[MMU_PAGE_1M].shift)
|
||||
mmu_huge_psize = MMU_PAGE_1M;
|
||||
|
||||
/* Calculate HPAGE_SHIFT and sanity check it */
|
||||
if (mmu_psize_defs[mmu_huge_psize].shift > 16 &&
|
||||
mmu_psize_defs[mmu_huge_psize].shift < 28)
|
||||
HPAGE_SHIFT = mmu_psize_defs[mmu_huge_psize].shift;
|
||||
else
|
||||
HPAGE_SHIFT = 0; /* No huge pages dude ! */
|
||||
#endif /* CONFIG_HUGETLB_PAGE */
|
||||
}
|
||||
|
||||
static int __init htab_dt_scan_pftsize(unsigned long node,
|
||||
const char *uname, int depth,
|
||||
void *data)
|
||||
{
|
||||
char *type = of_get_flat_dt_prop(node, "device_type", NULL);
|
||||
u32 *prop;
|
||||
|
||||
/* We are scanning "cpu" nodes only */
|
||||
if (type == NULL || strcmp(type, "cpu") != 0)
|
||||
return 0;
|
||||
|
||||
prop = (u32 *)of_get_flat_dt_prop(node, "ibm,pft-size", NULL);
|
||||
if (prop != NULL) {
|
||||
/* pft_size[0] is the NUMA CEC cookie */
|
||||
ppc64_pft_size = prop[1];
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long __init htab_get_table_size(void)
|
||||
{
|
||||
unsigned long rnd_mem_size, pteg_count;
|
||||
|
||||
/* If hash size wasn't obtained in prom.c, we calculate it now based on
|
||||
* the total RAM size
|
||||
/* If hash size isn't already provided by the platform, we try to
|
||||
* retreive it from the device-tree. If it's not there neither, we
|
||||
* calculate it now based on the total RAM size
|
||||
*/
|
||||
if (ppc64_pft_size == 0)
|
||||
of_scan_flat_dt(htab_dt_scan_pftsize, NULL);
|
||||
if (ppc64_pft_size)
|
||||
return 1UL << ppc64_pft_size;
|
||||
|
||||
|
@ -181,17 +390,21 @@ void __init htab_initialize(void)
|
|||
unsigned long table, htab_size_bytes;
|
||||
unsigned long pteg_count;
|
||||
unsigned long mode_rw;
|
||||
int i, use_largepages = 0;
|
||||
unsigned long base = 0, size = 0;
|
||||
int i;
|
||||
|
||||
extern unsigned long tce_alloc_start, tce_alloc_end;
|
||||
|
||||
DBG(" -> htab_initialize()\n");
|
||||
|
||||
/* Initialize page sizes */
|
||||
htab_init_page_sizes();
|
||||
|
||||
/*
|
||||
* 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 = get_hashtable_size();
|
||||
htab_size_bytes = htab_get_table_size();
|
||||
pteg_count = htab_size_bytes >> 7;
|
||||
|
||||
/* For debug, make the HTAB 1/8 as big as it normally would be. */
|
||||
|
@ -211,14 +424,11 @@ void __init htab_initialize(void)
|
|||
* the absolute address space.
|
||||
*/
|
||||
table = lmb_alloc(htab_size_bytes, htab_size_bytes);
|
||||
BUG_ON(table == 0);
|
||||
|
||||
DBG("Hash table allocated at %lx, size: %lx\n", table,
|
||||
htab_size_bytes);
|
||||
|
||||
if ( !table ) {
|
||||
ppc64_terminate_msg(0x20, "hpt space");
|
||||
loop_forever();
|
||||
}
|
||||
htab_address = abs_to_virt(table);
|
||||
|
||||
/* htab absolute addr + encoded htabsize */
|
||||
|
@ -234,8 +444,6 @@ void __init htab_initialize(void)
|
|||
* _NOT_ map it to avoid cache paradoxes as it's remapped non
|
||||
* cacheable later on
|
||||
*/
|
||||
if (cpu_has_feature(CPU_FTR_16M_PAGE))
|
||||
use_largepages = 1;
|
||||
|
||||
/* create bolted the linear mapping in the hash table */
|
||||
for (i=0; i < lmb.memory.cnt; i++) {
|
||||
|
@ -246,27 +454,32 @@ void __init htab_initialize(void)
|
|||
|
||||
#ifdef CONFIG_U3_DART
|
||||
/* Do not map the DART space. Fortunately, it will be aligned
|
||||
* in such a way that it will not cross two lmb regions and will
|
||||
* fit within a single 16Mb page.
|
||||
* The DART space is assumed to be a full 16Mb region even if we
|
||||
* only use 2Mb of that space. We will use more of it later for
|
||||
* AGP GART. We have to use a full 16Mb large page.
|
||||
* in such a way that it will not cross two lmb regions and
|
||||
* will fit within a single 16Mb page.
|
||||
* The DART space is assumed to be a full 16Mb region even if
|
||||
* we only use 2Mb of that space. We will use more of it later
|
||||
* for AGP GART. We have to use a full 16Mb large page.
|
||||
*/
|
||||
DBG("DART base: %lx\n", dart_tablebase);
|
||||
|
||||
if (dart_tablebase != 0 && dart_tablebase >= base
|
||||
&& dart_tablebase < (base + size)) {
|
||||
if (base != dart_tablebase)
|
||||
create_pte_mapping(base, dart_tablebase, mode_rw,
|
||||
use_largepages);
|
||||
BUG_ON(htab_bolt_mapping(base, dart_tablebase,
|
||||
base, mode_rw,
|
||||
mmu_linear_psize));
|
||||
if ((base + size) > (dart_tablebase + 16*MB))
|
||||
create_pte_mapping(dart_tablebase + 16*MB, base + size,
|
||||
mode_rw, use_largepages);
|
||||
BUG_ON(htab_bolt_mapping(dart_tablebase+16*MB,
|
||||
base + size,
|
||||
dart_tablebase+16*MB,
|
||||
mode_rw,
|
||||
mmu_linear_psize));
|
||||
continue;
|
||||
}
|
||||
#endif /* CONFIG_U3_DART */
|
||||
create_pte_mapping(base, base + size, mode_rw, use_largepages);
|
||||
}
|
||||
BUG_ON(htab_bolt_mapping(base, base + size, base,
|
||||
mode_rw, mmu_linear_psize));
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a memory_limit and we've allocated TCEs then we need to
|
||||
|
@ -282,8 +495,9 @@ void __init htab_initialize(void)
|
|||
if (base + size >= tce_alloc_start)
|
||||
tce_alloc_start = base + size + 1;
|
||||
|
||||
create_pte_mapping(tce_alloc_start, tce_alloc_end,
|
||||
mode_rw, use_largepages);
|
||||
BUG_ON(htab_bolt_mapping(tce_alloc_start, tce_alloc_end,
|
||||
tce_alloc_start, mode_rw,
|
||||
mmu_linear_psize));
|
||||
}
|
||||
|
||||
DBG(" <- htab_initialize()\n");
|
||||
|
@ -298,9 +512,6 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
|
|||
{
|
||||
struct page *page;
|
||||
|
||||
if (!pfn_valid(pte_pfn(pte)))
|
||||
return pp;
|
||||
|
||||
page = pte_page(pte);
|
||||
|
||||
/* page is dirty */
|
||||
|
@ -309,7 +520,7 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
|
|||
__flush_dcache_icache(page_address(page));
|
||||
set_bit(PG_arch_1, &page->flags);
|
||||
} else
|
||||
pp |= HW_NO_EXEC;
|
||||
pp |= HPTE_R_N;
|
||||
}
|
||||
return pp;
|
||||
}
|
||||
|
@ -325,94 +536,169 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
|
|||
unsigned long vsid;
|
||||
struct mm_struct *mm;
|
||||
pte_t *ptep;
|
||||
int ret;
|
||||
int user_region = 0;
|
||||
int local = 0;
|
||||
cpumask_t tmp;
|
||||
int rc, user_region = 0, local = 0;
|
||||
|
||||
if ((ea & ~REGION_MASK) >= PGTABLE_RANGE)
|
||||
return 1;
|
||||
DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n",
|
||||
ea, access, trap);
|
||||
|
||||
if ((ea & ~REGION_MASK) >= PGTABLE_RANGE) {
|
||||
DBG_LOW(" out of pgtable range !\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get region & vsid */
|
||||
switch (REGION_ID(ea)) {
|
||||
case USER_REGION_ID:
|
||||
user_region = 1;
|
||||
mm = current->mm;
|
||||
if (! mm)
|
||||
if (! mm) {
|
||||
DBG_LOW(" user region with no mm !\n");
|
||||
return 1;
|
||||
|
||||
}
|
||||
vsid = get_vsid(mm->context.id, ea);
|
||||
break;
|
||||
case VMALLOC_REGION_ID:
|
||||
mm = &init_mm;
|
||||
vsid = get_kernel_vsid(ea);
|
||||
break;
|
||||
#if 0
|
||||
case KERNEL_REGION_ID:
|
||||
/*
|
||||
* Should never get here - entire 0xC0... region is bolted.
|
||||
* Send the problem up to do_page_fault
|
||||
*/
|
||||
#endif
|
||||
default:
|
||||
/* Not a valid range
|
||||
* Send the problem up to do_page_fault
|
||||
*/
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
DBG_LOW(" mm=%p, mm->pgdir=%p, vsid=%016lx\n", mm, mm->pgd, vsid);
|
||||
|
||||
/* Get pgdir */
|
||||
pgdir = mm->pgd;
|
||||
|
||||
if (pgdir == NULL)
|
||||
return 1;
|
||||
|
||||
/* Check CPU locality */
|
||||
tmp = cpumask_of_cpu(smp_processor_id());
|
||||
if (user_region && cpus_equal(mm->cpu_vm_mask, tmp))
|
||||
local = 1;
|
||||
|
||||
/* Is this a huge page ? */
|
||||
if (unlikely(in_hugepage_area(mm->context, ea)))
|
||||
ret = hash_huge_page(mm, access, ea, vsid, local);
|
||||
else {
|
||||
ptep = find_linux_pte(pgdir, ea);
|
||||
if (ptep == NULL)
|
||||
return 1;
|
||||
ret = __hash_page(ea, access, vsid, ptep, trap, local);
|
||||
/* Handle hugepage regions */
|
||||
if (unlikely(in_hugepage_area(mm->context, ea))) {
|
||||
DBG_LOW(" -> huge page !\n");
|
||||
return hash_huge_page(mm, access, ea, vsid, local);
|
||||
}
|
||||
|
||||
return ret;
|
||||
/* Get PTE and page size from page tables */
|
||||
ptep = find_linux_pte(pgdir, ea);
|
||||
if (ptep == NULL || !pte_present(*ptep)) {
|
||||
DBG_LOW(" no PTE !\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PPC_64K_PAGES
|
||||
DBG_LOW(" i-pte: %016lx\n", pte_val(*ptep));
|
||||
#else
|
||||
DBG_LOW(" i-pte: %016lx %016lx\n", pte_val(*ptep),
|
||||
pte_val(*(ptep + PTRS_PER_PTE)));
|
||||
#endif
|
||||
/* Pre-check access permissions (will be re-checked atomically
|
||||
* in __hash_page_XX but this pre-check is a fast path
|
||||
*/
|
||||
if (access & ~pte_val(*ptep)) {
|
||||
DBG_LOW(" no access !\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Do actual hashing */
|
||||
#ifndef CONFIG_PPC_64K_PAGES
|
||||
rc = __hash_page_4K(ea, access, vsid, ptep, trap, local);
|
||||
#else
|
||||
if (mmu_virtual_psize == MMU_PAGE_64K)
|
||||
rc = __hash_page_64K(ea, access, vsid, ptep, trap, local);
|
||||
else
|
||||
rc = __hash_page_4K(ea, access, vsid, ptep, trap, local);
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
|
||||
#ifndef CONFIG_PPC_64K_PAGES
|
||||
DBG_LOW(" o-pte: %016lx\n", pte_val(*ptep));
|
||||
#else
|
||||
DBG_LOW(" o-pte: %016lx %016lx\n", pte_val(*ptep),
|
||||
pte_val(*(ptep + PTRS_PER_PTE)));
|
||||
#endif
|
||||
DBG_LOW(" -> rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void flush_hash_page(unsigned long va, pte_t pte, int local)
|
||||
void hash_preload(struct mm_struct *mm, unsigned long ea,
|
||||
unsigned long access, unsigned long trap)
|
||||
{
|
||||
unsigned long vpn, hash, secondary, slot;
|
||||
unsigned long huge = pte_huge(pte);
|
||||
unsigned long vsid;
|
||||
void *pgdir;
|
||||
pte_t *ptep;
|
||||
cpumask_t mask;
|
||||
unsigned long flags;
|
||||
int local = 0;
|
||||
|
||||
if (huge)
|
||||
vpn = va >> HPAGE_SHIFT;
|
||||
/* We don't want huge pages prefaulted for now
|
||||
*/
|
||||
if (unlikely(in_hugepage_area(mm->context, ea)))
|
||||
return;
|
||||
|
||||
DBG_LOW("hash_preload(mm=%p, mm->pgdir=%p, ea=%016lx, access=%lx,"
|
||||
" trap=%lx\n", mm, mm->pgd, ea, access, trap);
|
||||
|
||||
/* Get PTE, VSID, access mask */
|
||||
pgdir = mm->pgd;
|
||||
if (pgdir == NULL)
|
||||
return;
|
||||
ptep = find_linux_pte(pgdir, ea);
|
||||
if (!ptep)
|
||||
return;
|
||||
vsid = get_vsid(mm->context.id, ea);
|
||||
|
||||
/* Hash it in */
|
||||
local_irq_save(flags);
|
||||
mask = cpumask_of_cpu(smp_processor_id());
|
||||
if (cpus_equal(mm->cpu_vm_mask, mask))
|
||||
local = 1;
|
||||
#ifndef CONFIG_PPC_64K_PAGES
|
||||
__hash_page_4K(ea, access, vsid, ptep, trap, local);
|
||||
#else
|
||||
if (mmu_virtual_psize == MMU_PAGE_64K)
|
||||
__hash_page_64K(ea, access, vsid, ptep, trap, local);
|
||||
else
|
||||
vpn = va >> PAGE_SHIFT;
|
||||
hash = hpt_hash(vpn, huge);
|
||||
secondary = (pte_val(pte) & _PAGE_SECONDARY) >> 15;
|
||||
if (secondary)
|
||||
hash = ~hash;
|
||||
slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
|
||||
slot += (pte_val(pte) & _PAGE_GROUP_IX) >> 12;
|
||||
__hash_page_4K(ea, access, vsid, ptep, trap, local);
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
ppc_md.hpte_invalidate(slot, va, huge, local);
|
||||
void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int local)
|
||||
{
|
||||
unsigned long hash, index, shift, hidx, slot;
|
||||
|
||||
DBG_LOW("flush_hash_page(va=%016x)\n", va);
|
||||
pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
|
||||
hash = hpt_hash(va, shift);
|
||||
hidx = __rpte_to_hidx(pte, index);
|
||||
if (hidx & _PTEIDX_SECONDARY)
|
||||
hash = ~hash;
|
||||
slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
|
||||
slot += hidx & _PTEIDX_GROUP_IX;
|
||||
DBG_LOW(" sub %d: hash=%x, hidx=%x\n", index, slot, hidx);
|
||||
ppc_md.hpte_invalidate(slot, va, psize, local);
|
||||
} pte_iterate_hashed_end();
|
||||
}
|
||||
|
||||
void flush_hash_range(unsigned long number, int local)
|
||||
{
|
||||
if (ppc_md.flush_hash_range) {
|
||||
if (ppc_md.flush_hash_range)
|
||||
ppc_md.flush_hash_range(number, local);
|
||||
} else {
|
||||
else {
|
||||
int i;
|
||||
struct ppc64_tlb_batch *batch =
|
||||
&__get_cpu_var(ppc64_tlb_batch);
|
||||
|
||||
for (i = 0; i < number; i++)
|
||||
flush_hash_page(batch->vaddr[i], batch->pte[i], local);
|
||||
flush_hash_page(batch->vaddr[i], batch->pte[i],
|
||||
batch->psize, local);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -452,6 +738,18 @@ void __init htab_finish_init(void)
|
|||
extern unsigned int *htab_call_hpte_remove;
|
||||
extern unsigned int *htab_call_hpte_updatepp;
|
||||
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
extern unsigned int *ht64_call_hpte_insert1;
|
||||
extern unsigned int *ht64_call_hpte_insert2;
|
||||
extern unsigned int *ht64_call_hpte_remove;
|
||||
extern unsigned int *ht64_call_hpte_updatepp;
|
||||
|
||||
make_bl(ht64_call_hpte_insert1, ppc_md.hpte_insert);
|
||||
make_bl(ht64_call_hpte_insert2, ppc_md.hpte_insert);
|
||||
make_bl(ht64_call_hpte_remove, ppc_md.hpte_remove);
|
||||
make_bl(ht64_call_hpte_updatepp, ppc_md.hpte_updatepp);
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
|
||||
make_bl(htab_call_hpte_insert1, ppc_md.hpte_insert);
|
||||
make_bl(htab_call_hpte_insert2, ppc_md.hpte_insert);
|
||||
make_bl(htab_call_hpte_remove, ppc_md.hpte_remove);
|
||||
|
|
|
@ -47,10 +47,25 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
|
|||
pu = pud_offset(pg, addr);
|
||||
if (!pud_none(*pu)) {
|
||||
pm = pmd_offset(pu, addr);
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
/* Currently, we use the normal PTE offset within full
|
||||
* size PTE pages, thus our huge PTEs are scattered in
|
||||
* the PTE page and we do waste some. We may change
|
||||
* that in the future, but the current mecanism keeps
|
||||
* things much simpler
|
||||
*/
|
||||
if (!pmd_none(*pm)) {
|
||||
/* Note: pte_offset_* are all equivalent on
|
||||
* ppc64 as we don't have HIGHMEM
|
||||
*/
|
||||
pt = pte_offset_kernel(pm, addr);
|
||||
return pt;
|
||||
}
|
||||
#else /* CONFIG_PPC_64K_PAGES */
|
||||
/* On 4k pages, we put huge PTEs in the PMD page */
|
||||
pt = (pte_t *)pm;
|
||||
BUG_ON(!pmd_none(*pm)
|
||||
&& !(pte_present(*pt) && pte_huge(*pt)));
|
||||
return pt;
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,9 +89,16 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
|
|||
if (pu) {
|
||||
pm = pmd_alloc(mm, pu, addr);
|
||||
if (pm) {
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
/* See comment in huge_pte_offset. Note that if we ever
|
||||
* want to put the page size in the PMD, we would have
|
||||
* to open code our own pte_alloc* function in order
|
||||
* to populate and set the size atomically
|
||||
*/
|
||||
pt = pte_alloc_map(mm, pm, addr);
|
||||
#else /* CONFIG_PPC_64K_PAGES */
|
||||
pt = (pte_t *)pm;
|
||||
BUG_ON(!pmd_none(*pm)
|
||||
&& !(pte_present(*pt) && pte_huge(*pt)));
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
return pt;
|
||||
}
|
||||
}
|
||||
|
@ -84,35 +106,29 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#define HUGEPTE_BATCH_SIZE (HPAGE_SIZE / PMD_SIZE)
|
||||
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (pte_present(*ptep)) {
|
||||
pte_clear(mm, addr, ptep);
|
||||
/* We open-code pte_clear because we need to pass the right
|
||||
* argument to hpte_update (huge / !huge)
|
||||
*/
|
||||
unsigned long old = pte_update(ptep, ~0UL);
|
||||
if (old & _PAGE_HASHPTE)
|
||||
hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1);
|
||||
flush_tlb_pending();
|
||||
}
|
||||
|
||||
for (i = 0; i < HUGEPTE_BATCH_SIZE; i++) {
|
||||
*ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
|
||||
ptep++;
|
||||
}
|
||||
*ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
|
||||
}
|
||||
|
||||
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep)
|
||||
{
|
||||
unsigned long old = pte_update(ptep, ~0UL);
|
||||
int i;
|
||||
|
||||
if (old & _PAGE_HASHPTE)
|
||||
hpte_update(mm, addr, old, 0);
|
||||
|
||||
for (i = 1; i < HUGEPTE_BATCH_SIZE; i++)
|
||||
ptep[i] = __pte(0);
|
||||
hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1);
|
||||
*ptep = __pte(0);
|
||||
|
||||
return __pte(old);
|
||||
}
|
||||
|
@ -563,6 +579,8 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
|||
int lastshift;
|
||||
u16 areamask, curareas;
|
||||
|
||||
if (HPAGE_SHIFT == 0)
|
||||
return -EINVAL;
|
||||
if (len & ~HPAGE_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -619,19 +637,15 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access,
|
|||
unsigned long ea, unsigned long vsid, int local)
|
||||
{
|
||||
pte_t *ptep;
|
||||
unsigned long va, vpn;
|
||||
pte_t old_pte, new_pte;
|
||||
unsigned long rflags, prpn;
|
||||
unsigned long old_pte, new_pte;
|
||||
unsigned long va, rflags, pa;
|
||||
long slot;
|
||||
int err = 1;
|
||||
|
||||
spin_lock(&mm->page_table_lock);
|
||||
|
||||
ptep = huge_pte_offset(mm, ea);
|
||||
|
||||
/* Search the Linux page table for a match with va */
|
||||
va = (vsid << 28) | (ea & 0x0fffffff);
|
||||
vpn = va >> HPAGE_SHIFT;
|
||||
|
||||
/*
|
||||
* If no pte found or not present, send the problem up to
|
||||
|
@ -640,8 +654,6 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access,
|
|||
if (unlikely(!ptep || pte_none(*ptep)))
|
||||
goto out;
|
||||
|
||||
/* BUG_ON(pte_bad(*ptep)); */
|
||||
|
||||
/*
|
||||
* Check the user's access rights to the page. If access should be
|
||||
* prevented then send the problem up to do_page_fault.
|
||||
|
@ -661,58 +673,64 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access,
|
|||
*/
|
||||
|
||||
|
||||
old_pte = *ptep;
|
||||
new_pte = old_pte;
|
||||
do {
|
||||
old_pte = pte_val(*ptep);
|
||||
if (old_pte & _PAGE_BUSY)
|
||||
goto out;
|
||||
new_pte = old_pte | _PAGE_BUSY |
|
||||
_PAGE_ACCESSED | _PAGE_HASHPTE;
|
||||
} while(old_pte != __cmpxchg_u64((unsigned long *)ptep,
|
||||
old_pte, new_pte));
|
||||
|
||||
rflags = 0x2 | (! (pte_val(new_pte) & _PAGE_RW));
|
||||
rflags = 0x2 | (!(new_pte & _PAGE_RW));
|
||||
/* _PAGE_EXEC -> HW_NO_EXEC since it's inverted */
|
||||
rflags |= ((pte_val(new_pte) & _PAGE_EXEC) ? 0 : HW_NO_EXEC);
|
||||
rflags |= ((new_pte & _PAGE_EXEC) ? 0 : HPTE_R_N);
|
||||
|
||||
/* Check if pte already has an hpte (case 2) */
|
||||
if (unlikely(pte_val(old_pte) & _PAGE_HASHPTE)) {
|
||||
if (unlikely(old_pte & _PAGE_HASHPTE)) {
|
||||
/* There MIGHT be an HPTE for this pte */
|
||||
unsigned long hash, slot;
|
||||
|
||||
hash = hpt_hash(vpn, 1);
|
||||
if (pte_val(old_pte) & _PAGE_SECONDARY)
|
||||
hash = hpt_hash(va, HPAGE_SHIFT);
|
||||
if (old_pte & _PAGE_F_SECOND)
|
||||
hash = ~hash;
|
||||
slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
|
||||
slot += (pte_val(old_pte) & _PAGE_GROUP_IX) >> 12;
|
||||
slot += (old_pte & _PAGE_F_GIX) >> 12;
|
||||
|
||||
if (ppc_md.hpte_updatepp(slot, rflags, va, 1, local) == -1)
|
||||
pte_val(old_pte) &= ~_PAGE_HPTEFLAGS;
|
||||
old_pte &= ~_PAGE_HPTEFLAGS;
|
||||
}
|
||||
|
||||
if (likely(!(pte_val(old_pte) & _PAGE_HASHPTE))) {
|
||||
unsigned long hash = hpt_hash(vpn, 1);
|
||||
if (likely(!(old_pte & _PAGE_HASHPTE))) {
|
||||
unsigned long hash = hpt_hash(va, HPAGE_SHIFT);
|
||||
unsigned long hpte_group;
|
||||
|
||||
prpn = pte_pfn(old_pte);
|
||||
pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT;
|
||||
|
||||
repeat:
|
||||
hpte_group = ((hash & htab_hash_mask) *
|
||||
HPTES_PER_GROUP) & ~0x7UL;
|
||||
|
||||
/* Update the linux pte with the HPTE slot */
|
||||
pte_val(new_pte) &= ~_PAGE_HPTEFLAGS;
|
||||
pte_val(new_pte) |= _PAGE_HASHPTE;
|
||||
/* clear HPTE slot informations in new PTE */
|
||||
new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE;
|
||||
|
||||
/* Add in WIMG bits */
|
||||
/* XXX We should store these in the pte */
|
||||
/* --BenH: I think they are ... */
|
||||
rflags |= _PAGE_COHERENT;
|
||||
|
||||
slot = ppc_md.hpte_insert(hpte_group, va, prpn,
|
||||
HPTE_V_LARGE, rflags);
|
||||
/* Insert into the hash table, primary slot */
|
||||
slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, 0,
|
||||
mmu_huge_psize);
|
||||
|
||||
/* Primary is full, try the secondary */
|
||||
if (unlikely(slot == -1)) {
|
||||
pte_val(new_pte) |= _PAGE_SECONDARY;
|
||||
new_pte |= _PAGE_F_SECOND;
|
||||
hpte_group = ((~hash & htab_hash_mask) *
|
||||
HPTES_PER_GROUP) & ~0x7UL;
|
||||
slot = ppc_md.hpte_insert(hpte_group, va, prpn,
|
||||
HPTE_V_LARGE |
|
||||
slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags,
|
||||
HPTE_V_SECONDARY,
|
||||
rflags);
|
||||
mmu_huge_psize);
|
||||
if (slot == -1) {
|
||||
if (mftb() & 0x1)
|
||||
hpte_group = ((hash & htab_hash_mask) *
|
||||
|
@ -726,20 +744,18 @@ repeat:
|
|||
if (unlikely(slot == -2))
|
||||
panic("hash_huge_page: pte_insert failed\n");
|
||||
|
||||
pte_val(new_pte) |= (slot<<12) & _PAGE_GROUP_IX;
|
||||
|
||||
/*
|
||||
* No need to use ldarx/stdcx here because all who
|
||||
* might be updating the pte will hold the
|
||||
* page_table_lock
|
||||
*/
|
||||
*ptep = new_pte;
|
||||
new_pte |= (slot << 12) & _PAGE_F_GIX;
|
||||
}
|
||||
|
||||
/*
|
||||
* No need to use ldarx/stdcx here because all who
|
||||
* might be updating the pte will hold the
|
||||
* page_table_lock
|
||||
*/
|
||||
*ptep = __pte(new_pte & ~_PAGE_BUSY);
|
||||
|
||||
err = 0;
|
||||
|
||||
out:
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -188,12 +188,21 @@ static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags)
|
|||
memset(addr, 0, kmem_cache_size(cache));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
static const int pgtable_cache_size[2] = {
|
||||
PTE_TABLE_SIZE, PGD_TABLE_SIZE
|
||||
};
|
||||
static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
|
||||
"pte_pmd_cache", "pgd_cache",
|
||||
};
|
||||
#else
|
||||
static const int pgtable_cache_size[2] = {
|
||||
PTE_TABLE_SIZE, PMD_TABLE_SIZE
|
||||
};
|
||||
static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
|
||||
"pgd_pte_cache", "pud_pmd_cache",
|
||||
};
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
|
||||
kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)];
|
||||
|
||||
|
@ -201,19 +210,14 @@ void pgtable_cache_init(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
BUILD_BUG_ON(PTE_TABLE_SIZE != pgtable_cache_size[PTE_CACHE_NUM]);
|
||||
BUILD_BUG_ON(PMD_TABLE_SIZE != pgtable_cache_size[PMD_CACHE_NUM]);
|
||||
BUILD_BUG_ON(PUD_TABLE_SIZE != pgtable_cache_size[PUD_CACHE_NUM]);
|
||||
BUILD_BUG_ON(PGD_TABLE_SIZE != pgtable_cache_size[PGD_CACHE_NUM]);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pgtable_cache_size); i++) {
|
||||
int size = pgtable_cache_size[i];
|
||||
const char *name = pgtable_cache_name[i];
|
||||
|
||||
pgtable_cache[i] = kmem_cache_create(name,
|
||||
size, size,
|
||||
SLAB_HWCACHE_ALIGN
|
||||
| SLAB_MUST_HWCACHE_ALIGN,
|
||||
SLAB_HWCACHE_ALIGN |
|
||||
SLAB_MUST_HWCACHE_ALIGN,
|
||||
zero_ctor,
|
||||
NULL);
|
||||
if (! pgtable_cache[i])
|
||||
|
|
|
@ -61,6 +61,9 @@ int init_bootmem_done;
|
|||
int mem_init_done;
|
||||
unsigned long memory_limit;
|
||||
|
||||
extern void hash_preload(struct mm_struct *mm, unsigned long ea,
|
||||
unsigned long access, unsigned long trap);
|
||||
|
||||
/*
|
||||
* This is called by /dev/mem to know if a given address has to
|
||||
* be mapped non-cacheable or not
|
||||
|
@ -493,18 +496,10 @@ EXPORT_SYMBOL(flush_icache_user_range);
|
|||
void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
|
||||
pte_t pte)
|
||||
{
|
||||
/* handle i-cache coherency */
|
||||
unsigned long pfn = pte_pfn(pte);
|
||||
#ifdef CONFIG_PPC32
|
||||
pmd_t *pmd;
|
||||
#else
|
||||
unsigned long vsid;
|
||||
void *pgdir;
|
||||
pte_t *ptep;
|
||||
int local = 0;
|
||||
cpumask_t tmp;
|
||||
unsigned long flags;
|
||||
#ifdef CONFIG_PPC_STD_MMU
|
||||
unsigned long access = 0, trap;
|
||||
#endif
|
||||
unsigned long pfn = pte_pfn(pte);
|
||||
|
||||
/* handle i-cache coherency */
|
||||
if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE) &&
|
||||
|
@ -535,30 +530,21 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
|
|||
/* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */
|
||||
if (!pte_young(pte) || address >= TASK_SIZE)
|
||||
return;
|
||||
#ifdef CONFIG_PPC32
|
||||
if (Hash == 0)
|
||||
|
||||
/* We try to figure out if we are coming from an instruction
|
||||
* access fault and pass that down to __hash_page so we avoid
|
||||
* double-faulting on execution of fresh text. We have to test
|
||||
* for regs NULL since init will get here first thing at boot
|
||||
*
|
||||
* We also avoid filling the hash if not coming from a fault
|
||||
*/
|
||||
if (current->thread.regs == NULL)
|
||||
return;
|
||||
pmd = pmd_offset(pgd_offset(vma->vm_mm, address), address);
|
||||
if (!pmd_none(*pmd))
|
||||
add_hash_page(vma->vm_mm->context, address, pmd_val(*pmd));
|
||||
#else
|
||||
pgdir = vma->vm_mm->pgd;
|
||||
if (pgdir == NULL)
|
||||
trap = TRAP(current->thread.regs);
|
||||
if (trap == 0x400)
|
||||
access |= _PAGE_EXEC;
|
||||
else if (trap != 0x300)
|
||||
return;
|
||||
|
||||
ptep = find_linux_pte(pgdir, address);
|
||||
if (!ptep)
|
||||
return;
|
||||
|
||||
vsid = get_vsid(vma->vm_mm->context.id, address);
|
||||
|
||||
local_irq_save(flags);
|
||||
tmp = cpumask_of_cpu(smp_processor_id());
|
||||
if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp))
|
||||
local = 1;
|
||||
|
||||
__hash_page(address, 0, vsid, ptep, 0x300, local);
|
||||
local_irq_restore(flags);
|
||||
#endif
|
||||
#endif
|
||||
hash_preload(vma->vm_mm, address, access, trap);
|
||||
#endif /* CONFIG_PPC_STD_MMU */
|
||||
}
|
||||
|
|
|
@ -101,7 +101,6 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
|
|||
pud_t *pudp;
|
||||
pmd_t *pmdp;
|
||||
pte_t *ptep;
|
||||
unsigned long vsid;
|
||||
|
||||
if (mem_init_done) {
|
||||
pgdp = pgd_offset_k(ea);
|
||||
|
@ -117,28 +116,15 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
|
|||
set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
|
||||
__pgprot(flags)));
|
||||
} else {
|
||||
unsigned long va, vpn, hash, hpteg;
|
||||
|
||||
/*
|
||||
* If the mm subsystem is not fully up, we cannot create a
|
||||
* linux page table entry for this mapping. Simply bolt an
|
||||
* entry in the hardware page table.
|
||||
*
|
||||
*/
|
||||
vsid = get_kernel_vsid(ea);
|
||||
va = (vsid << 28) | (ea & 0xFFFFFFF);
|
||||
vpn = va >> PAGE_SHIFT;
|
||||
|
||||
hash = hpt_hash(vpn, 0);
|
||||
|
||||
hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
|
||||
|
||||
/* Panic if a pte grpup is full */
|
||||
if (ppc_md.hpte_insert(hpteg, va, pa >> PAGE_SHIFT,
|
||||
HPTE_V_BOLTED,
|
||||
_PAGE_NO_CACHE|_PAGE_GUARDED|PP_RWXX)
|
||||
== -1) {
|
||||
panic("map_io_page: could not insert mapping");
|
||||
}
|
||||
if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags,
|
||||
mmu_virtual_psize))
|
||||
panic("Can't map bolted IO mapping");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -178,6 +178,21 @@ void __init setbat(int index, unsigned long virt, unsigned long phys,
|
|||
bat_addrs[index].phys = phys;
|
||||
}
|
||||
|
||||
/*
|
||||
* Preload a translation in the hash table
|
||||
*/
|
||||
void hash_preload(struct mm_struct *mm, unsigned long ea,
|
||||
unsigned long access, unsigned long trap)
|
||||
{
|
||||
pmd_t *pmd;
|
||||
|
||||
if (Hash == 0)
|
||||
return;
|
||||
pmd = pmd_offset(pgd_offset(vma->vm_mm, address), address);
|
||||
if (!pmd_none(*pmd))
|
||||
add_hash_page(vma->vm_mm->context, address, pmd_val(*pmd));
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the hash table and patch the instructions in hashtable.S.
|
||||
*/
|
||||
|
|
|
@ -14,14 +14,32 @@
|
|||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/paca.h>
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
extern void slb_allocate(unsigned long ea);
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
#else
|
||||
#define DBG(fmt...)
|
||||
#endif
|
||||
|
||||
extern void slb_allocate_realmode(unsigned long ea);
|
||||
extern void slb_allocate_user(unsigned long ea);
|
||||
|
||||
static void slb_allocate(unsigned long ea)
|
||||
{
|
||||
/* Currently, we do real mode for all SLBs including user, but
|
||||
* that will change if we bring back dynamic VSIDs
|
||||
*/
|
||||
slb_allocate_realmode(ea);
|
||||
}
|
||||
|
||||
static inline unsigned long mk_esid_data(unsigned long ea, unsigned long slot)
|
||||
{
|
||||
|
@ -46,13 +64,15 @@ static void slb_flush_and_rebolt(void)
|
|||
{
|
||||
/* If you change this make sure you change SLB_NUM_BOLTED
|
||||
* appropriately too. */
|
||||
unsigned long ksp_flags = SLB_VSID_KERNEL;
|
||||
unsigned long linear_llp, virtual_llp, lflags, vflags;
|
||||
unsigned long ksp_esid_data;
|
||||
|
||||
WARN_ON(!irqs_disabled());
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_16M_PAGE))
|
||||
ksp_flags |= SLB_VSID_L;
|
||||
linear_llp = mmu_psize_defs[mmu_linear_psize].sllp;
|
||||
virtual_llp = mmu_psize_defs[mmu_virtual_psize].sllp;
|
||||
lflags = SLB_VSID_KERNEL | linear_llp;
|
||||
vflags = SLB_VSID_KERNEL | virtual_llp;
|
||||
|
||||
ksp_esid_data = mk_esid_data(get_paca()->kstack, 2);
|
||||
if ((ksp_esid_data & ESID_MASK) == KERNELBASE)
|
||||
|
@ -67,9 +87,9 @@ static void slb_flush_and_rebolt(void)
|
|||
/* Slot 2 - kernel stack */
|
||||
"slbmte %2,%3\n"
|
||||
"isync"
|
||||
:: "r"(mk_vsid_data(VMALLOCBASE, SLB_VSID_KERNEL)),
|
||||
:: "r"(mk_vsid_data(VMALLOCBASE, vflags)),
|
||||
"r"(mk_esid_data(VMALLOCBASE, 1)),
|
||||
"r"(mk_vsid_data(ksp_esid_data, ksp_flags)),
|
||||
"r"(mk_vsid_data(ksp_esid_data, lflags)),
|
||||
"r"(ksp_esid_data)
|
||||
: "memory");
|
||||
}
|
||||
|
@ -102,6 +122,9 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
|
|||
|
||||
get_paca()->slb_cache_ptr = 0;
|
||||
get_paca()->context = mm->context;
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
get_paca()->pgdir = mm->pgd;
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
|
||||
/*
|
||||
* preload some userspace segments into the SLB.
|
||||
|
@ -131,28 +154,77 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
|
|||
slb_allocate(unmapped_base);
|
||||
}
|
||||
|
||||
static inline void patch_slb_encoding(unsigned int *insn_addr,
|
||||
unsigned int immed)
|
||||
{
|
||||
/* Assume the instruction had a "0" immediate value, just
|
||||
* "or" in the new value
|
||||
*/
|
||||
*insn_addr |= immed;
|
||||
flush_icache_range((unsigned long)insn_addr, 4+
|
||||
(unsigned long)insn_addr);
|
||||
}
|
||||
|
||||
void slb_initialize(void)
|
||||
{
|
||||
unsigned long linear_llp, virtual_llp;
|
||||
static int slb_encoding_inited;
|
||||
extern unsigned int *slb_miss_kernel_load_linear;
|
||||
extern unsigned int *slb_miss_kernel_load_virtual;
|
||||
extern unsigned int *slb_miss_user_load_normal;
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
extern unsigned int *slb_miss_user_load_huge;
|
||||
unsigned long huge_llp;
|
||||
|
||||
huge_llp = mmu_psize_defs[mmu_huge_psize].sllp;
|
||||
#endif
|
||||
|
||||
/* Prepare our SLB miss handler based on our page size */
|
||||
linear_llp = mmu_psize_defs[mmu_linear_psize].sllp;
|
||||
virtual_llp = mmu_psize_defs[mmu_virtual_psize].sllp;
|
||||
if (!slb_encoding_inited) {
|
||||
slb_encoding_inited = 1;
|
||||
patch_slb_encoding(slb_miss_kernel_load_linear,
|
||||
SLB_VSID_KERNEL | linear_llp);
|
||||
patch_slb_encoding(slb_miss_kernel_load_virtual,
|
||||
SLB_VSID_KERNEL | virtual_llp);
|
||||
patch_slb_encoding(slb_miss_user_load_normal,
|
||||
SLB_VSID_USER | virtual_llp);
|
||||
|
||||
DBG("SLB: linear LLP = %04x\n", linear_llp);
|
||||
DBG("SLB: virtual LLP = %04x\n", virtual_llp);
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
patch_slb_encoding(slb_miss_user_load_huge,
|
||||
SLB_VSID_USER | huge_llp);
|
||||
DBG("SLB: huge LLP = %04x\n", huge_llp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* On iSeries the bolted entries have already been set up by
|
||||
* the hypervisor from the lparMap data in head.S */
|
||||
#ifndef CONFIG_PPC_ISERIES
|
||||
unsigned long flags = SLB_VSID_KERNEL;
|
||||
{
|
||||
unsigned long lflags, vflags;
|
||||
|
||||
/* Invalidate the entire SLB (even slot 0) & all the ERATS */
|
||||
if (cpu_has_feature(CPU_FTR_16M_PAGE))
|
||||
flags |= SLB_VSID_L;
|
||||
lflags = SLB_VSID_KERNEL | linear_llp;
|
||||
vflags = SLB_VSID_KERNEL | virtual_llp;
|
||||
|
||||
asm volatile("isync":::"memory");
|
||||
asm volatile("slbmte %0,%0"::"r" (0) : "memory");
|
||||
/* Invalidate the entire SLB (even slot 0) & all the ERATS */
|
||||
asm volatile("isync":::"memory");
|
||||
asm volatile("slbmte %0,%0"::"r" (0) : "memory");
|
||||
asm volatile("isync; slbia; isync":::"memory");
|
||||
create_slbe(KERNELBASE, flags, 0);
|
||||
create_slbe(VMALLOCBASE, SLB_VSID_KERNEL, 1);
|
||||
create_slbe(KERNELBASE, lflags, 0);
|
||||
|
||||
/* VMALLOC space has 4K pages always for now */
|
||||
create_slbe(VMALLOCBASE, vflags, 1);
|
||||
|
||||
/* We don't bolt the stack for the time being - we're in boot,
|
||||
* so the stack is in the bolted segment. By the time it goes
|
||||
* elsewhere, we'll call _switch() which will bolt in the new
|
||||
* one. */
|
||||
asm volatile("isync":::"memory");
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_PPC_ISERIES */
|
||||
|
||||
get_paca()->stab_rr = SLB_NUM_BOLTED;
|
||||
}
|
||||
|
|
|
@ -18,25 +18,161 @@
|
|||
|
||||
#include <linux/config.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/ppc_asm.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
/* void slb_allocate(unsigned long ea);
|
||||
/* void slb_allocate_realmode(unsigned long ea);
|
||||
*
|
||||
* Create an SLB entry for the given EA (user or kernel).
|
||||
* r3 = faulting address, r13 = PACA
|
||||
* r9, r10, r11 are clobbered by this function
|
||||
* No other registers are examined or changed.
|
||||
*/
|
||||
_GLOBAL(slb_allocate)
|
||||
/*
|
||||
* First find a slot, round robin. Previously we tried to find
|
||||
* a free slot first but that took too long. Unfortunately we
|
||||
* dont have any LRU information to help us choose a slot.
|
||||
_GLOBAL(slb_allocate_realmode)
|
||||
/* r3 = faulting address */
|
||||
|
||||
srdi r9,r3,60 /* get region */
|
||||
srdi r10,r3,28 /* get esid */
|
||||
cmpldi cr7,r9,0xc /* cmp KERNELBASE for later use */
|
||||
|
||||
/* r3 = address, r10 = esid, cr7 = <>KERNELBASE */
|
||||
blt cr7,0f /* user or kernel? */
|
||||
|
||||
/* kernel address: proto-VSID = ESID */
|
||||
/* WARNING - MAGIC: we don't use the VSID 0xfffffffff, but
|
||||
* this code will generate the protoVSID 0xfffffffff for the
|
||||
* top segment. That's ok, the scramble below will translate
|
||||
* it to VSID 0, which is reserved as a bad VSID - one which
|
||||
* will never have any pages in it. */
|
||||
|
||||
/* Check if hitting the linear mapping of the vmalloc/ioremap
|
||||
* kernel space
|
||||
*/
|
||||
bne cr7,1f
|
||||
|
||||
/* Linear mapping encoding bits, the "li" instruction below will
|
||||
* be patched by the kernel at boot
|
||||
*/
|
||||
_GLOBAL(slb_miss_kernel_load_linear)
|
||||
li r11,0
|
||||
b slb_finish_load
|
||||
|
||||
1: /* vmalloc/ioremap mapping encoding bits, the "li" instruction below
|
||||
* will be patched by the kernel at boot
|
||||
*/
|
||||
_GLOBAL(slb_miss_kernel_load_virtual)
|
||||
li r11,0
|
||||
b slb_finish_load
|
||||
|
||||
|
||||
0: /* user address: proto-VSID = context << 15 | ESID. First check
|
||||
* if the address is within the boundaries of the user region
|
||||
*/
|
||||
srdi. r9,r10,USER_ESID_BITS
|
||||
bne- 8f /* invalid ea bits set */
|
||||
|
||||
/* Figure out if the segment contains huge pages */
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
BEGIN_FTR_SECTION
|
||||
b 1f
|
||||
END_FTR_SECTION_IFCLR(CPU_FTR_16M_PAGE)
|
||||
lhz r9,PACAHIGHHTLBAREAS(r13)
|
||||
srdi r11,r10,(HTLB_AREA_SHIFT-SID_SHIFT)
|
||||
srd r9,r9,r11
|
||||
lhz r11,PACALOWHTLBAREAS(r13)
|
||||
srd r11,r11,r10
|
||||
or. r9,r9,r11
|
||||
beq 1f
|
||||
_GLOBAL(slb_miss_user_load_huge)
|
||||
li r11,0
|
||||
b 2f
|
||||
1:
|
||||
#endif /* CONFIG_HUGETLB_PAGE */
|
||||
|
||||
_GLOBAL(slb_miss_user_load_normal)
|
||||
li r11,0
|
||||
|
||||
2:
|
||||
ld r9,PACACONTEXTID(r13)
|
||||
rldimi r10,r9,USER_ESID_BITS,0
|
||||
b slb_finish_load
|
||||
|
||||
8: /* invalid EA */
|
||||
li r10,0 /* BAD_VSID */
|
||||
li r11,SLB_VSID_USER /* flags don't much matter */
|
||||
b slb_finish_load
|
||||
|
||||
#ifdef __DISABLED__
|
||||
|
||||
/* void slb_allocate_user(unsigned long ea);
|
||||
*
|
||||
* Create an SLB entry for the given EA (user or kernel).
|
||||
* r3 = faulting address, r13 = PACA
|
||||
* r9, r10, r11 are clobbered by this function
|
||||
* No other registers are examined or changed.
|
||||
*
|
||||
* It is called with translation enabled in order to be able to walk the
|
||||
* page tables. This is not currently used.
|
||||
*/
|
||||
_GLOBAL(slb_allocate_user)
|
||||
/* r3 = faulting address */
|
||||
srdi r10,r3,28 /* get esid */
|
||||
|
||||
crset 4*cr7+lt /* set "user" flag for later */
|
||||
|
||||
/* check if we fit in the range covered by the pagetables*/
|
||||
srdi. r9,r3,PGTABLE_EADDR_SIZE
|
||||
crnot 4*cr0+eq,4*cr0+eq
|
||||
beqlr
|
||||
|
||||
/* now we need to get to the page tables in order to get the page
|
||||
* size encoding from the PMD. In the future, we'll be able to deal
|
||||
* with 1T segments too by getting the encoding from the PGD instead
|
||||
*/
|
||||
ld r9,PACAPGDIR(r13)
|
||||
cmpldi cr0,r9,0
|
||||
beqlr
|
||||
rlwinm r11,r10,8,25,28
|
||||
ldx r9,r9,r11 /* get pgd_t */
|
||||
cmpldi cr0,r9,0
|
||||
beqlr
|
||||
rlwinm r11,r10,3,17,28
|
||||
ldx r9,r9,r11 /* get pmd_t */
|
||||
cmpldi cr0,r9,0
|
||||
beqlr
|
||||
|
||||
/* build vsid flags */
|
||||
andi. r11,r9,SLB_VSID_LLP
|
||||
ori r11,r11,SLB_VSID_USER
|
||||
|
||||
/* get context to calculate proto-VSID */
|
||||
ld r9,PACACONTEXTID(r13)
|
||||
rldimi r10,r9,USER_ESID_BITS,0
|
||||
|
||||
/* fall through slb_finish_load */
|
||||
|
||||
#endif /* __DISABLED__ */
|
||||
|
||||
|
||||
/*
|
||||
* Finish loading of an SLB entry and return
|
||||
*
|
||||
* r3 = EA, r10 = proto-VSID, r11 = flags, clobbers r9, cr7 = <>KERNELBASE
|
||||
*/
|
||||
slb_finish_load:
|
||||
ASM_VSID_SCRAMBLE(r10,r9)
|
||||
rldimi r11,r10,SLB_VSID_SHIFT,16 /* combine VSID and flags */
|
||||
|
||||
/* r3 = EA, r11 = VSID data */
|
||||
/*
|
||||
* Find a slot, round robin. Previously we tried to find a
|
||||
* free slot first but that took too long. Unfortunately we
|
||||
* dont have any LRU information to help us choose a slot.
|
||||
*/
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
/*
|
||||
* On iSeries, the "bolted" stack segment can be cast out on
|
||||
|
@ -45,9 +181,9 @@ _GLOBAL(slb_allocate)
|
|||
*/
|
||||
ld r9,PACAKSAVE(r13)
|
||||
clrrdi r9,r9,28
|
||||
clrrdi r11,r3,28
|
||||
clrrdi r3,r3,28
|
||||
li r10,SLB_NUM_BOLTED-1 /* Stack goes in last bolted slot */
|
||||
cmpld r9,r11
|
||||
cmpld r9,r3
|
||||
beq 3f
|
||||
#endif /* CONFIG_PPC_ISERIES */
|
||||
|
||||
|
@ -61,63 +197,12 @@ _GLOBAL(slb_allocate)
|
|||
|
||||
4:
|
||||
std r10,PACASTABRR(r13)
|
||||
|
||||
3:
|
||||
/* r3 = faulting address, r10 = entry */
|
||||
rldimi r3,r10,0,36 /* r3= EA[0:35] | entry */
|
||||
oris r10,r3,SLB_ESID_V@h /* r3 |= SLB_ESID_V */
|
||||
|
||||
srdi r9,r3,60 /* get region */
|
||||
srdi r3,r3,28 /* get esid */
|
||||
cmpldi cr7,r9,0xc /* cmp KERNELBASE for later use */
|
||||
|
||||
rldimi r10,r3,28,0 /* r10= ESID<<28 | entry */
|
||||
oris r10,r10,SLB_ESID_V@h /* r10 |= SLB_ESID_V */
|
||||
|
||||
/* r3 = esid, r10 = esid_data, cr7 = <>KERNELBASE */
|
||||
|
||||
blt cr7,0f /* user or kernel? */
|
||||
|
||||
/* kernel address: proto-VSID = ESID */
|
||||
/* WARNING - MAGIC: we don't use the VSID 0xfffffffff, but
|
||||
* this code will generate the protoVSID 0xfffffffff for the
|
||||
* top segment. That's ok, the scramble below will translate
|
||||
* it to VSID 0, which is reserved as a bad VSID - one which
|
||||
* will never have any pages in it. */
|
||||
li r11,SLB_VSID_KERNEL
|
||||
BEGIN_FTR_SECTION
|
||||
bne cr7,9f
|
||||
li r11,(SLB_VSID_KERNEL|SLB_VSID_L)
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
|
||||
b 9f
|
||||
|
||||
0: /* user address: proto-VSID = context<<15 | ESID */
|
||||
srdi. r9,r3,USER_ESID_BITS
|
||||
bne- 8f /* invalid ea bits set */
|
||||
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
BEGIN_FTR_SECTION
|
||||
lhz r9,PACAHIGHHTLBAREAS(r13)
|
||||
srdi r11,r3,(HTLB_AREA_SHIFT-SID_SHIFT)
|
||||
srd r9,r9,r11
|
||||
lhz r11,PACALOWHTLBAREAS(r13)
|
||||
srd r11,r11,r3
|
||||
or r9,r9,r11
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
|
||||
#endif /* CONFIG_HUGETLB_PAGE */
|
||||
|
||||
li r11,SLB_VSID_USER
|
||||
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
BEGIN_FTR_SECTION
|
||||
rldimi r11,r9,8,55 /* shift masked bit into SLB_VSID_L */
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
|
||||
#endif /* CONFIG_HUGETLB_PAGE */
|
||||
|
||||
ld r9,PACACONTEXTID(r13)
|
||||
rldimi r3,r9,USER_ESID_BITS,0
|
||||
|
||||
9: /* r3 = protovsid, r11 = flags, r10 = esid_data, cr7 = <>KERNELBASE */
|
||||
ASM_VSID_SCRAMBLE(r3,r9)
|
||||
|
||||
rldimi r11,r3,SLB_VSID_SHIFT,16 /* combine VSID and flags */
|
||||
/* r3 = ESID data, r11 = VSID data */
|
||||
|
||||
/*
|
||||
* No need for an isync before or after this slbmte. The exception
|
||||
|
@ -125,7 +210,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
|
|||
*/
|
||||
slbmte r11,r10
|
||||
|
||||
bgelr cr7 /* we're done for kernel addresses */
|
||||
/* we're done for kernel addresses */
|
||||
crclr 4*cr0+eq /* set result to "success" */
|
||||
bgelr cr7
|
||||
|
||||
/* Update the slb cache */
|
||||
lhz r3,PACASLBCACHEPTR(r13) /* offset = paca->slb_cache_ptr */
|
||||
|
@ -143,9 +230,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
|
|||
li r3,SLB_CACHE_ENTRIES+1
|
||||
2:
|
||||
sth r3,PACASLBCACHEPTR(r13) /* paca->slb_cache_ptr = offset */
|
||||
crclr 4*cr0+eq /* set result to "success" */
|
||||
blr
|
||||
|
||||
8: /* invalid EA */
|
||||
li r3,0 /* BAD_VSID */
|
||||
li r11,SLB_VSID_USER /* flags don't much matter */
|
||||
b 9b
|
||||
|
|
|
@ -26,7 +26,6 @@ struct stab_entry {
|
|||
unsigned long vsid_data;
|
||||
};
|
||||
|
||||
/* Both the segment table and SLB code uses the following cache */
|
||||
#define NR_STAB_CACHE_ENTRIES 8
|
||||
DEFINE_PER_CPU(long, stab_cache_ptr);
|
||||
DEFINE_PER_CPU(long, stab_cache[NR_STAB_CACHE_ENTRIES]);
|
||||
|
@ -186,7 +185,7 @@ void switch_stab(struct task_struct *tsk, struct mm_struct *mm)
|
|||
/* Never flush the first entry. */
|
||||
ste += 1;
|
||||
for (entry = 1;
|
||||
entry < (PAGE_SIZE / sizeof(struct stab_entry));
|
||||
entry < (HW_PAGE_SIZE / sizeof(struct stab_entry));
|
||||
entry++, ste++) {
|
||||
unsigned long ea;
|
||||
ea = ste->esid_data & ESID_MASK;
|
||||
|
@ -200,6 +199,10 @@ void switch_stab(struct task_struct *tsk, struct mm_struct *mm)
|
|||
|
||||
__get_cpu_var(stab_cache_ptr) = 0;
|
||||
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
get_paca()->pgdir = mm->pgd;
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
|
||||
/* Now preload some entries for the new task */
|
||||
if (test_tsk_thread_flag(tsk, TIF_32BIT))
|
||||
unmapped_base = TASK_UNMAPPED_BASE_USER32;
|
||||
|
@ -223,8 +226,6 @@ void switch_stab(struct task_struct *tsk, struct mm_struct *mm)
|
|||
asm volatile("sync" : : : "memory");
|
||||
}
|
||||
|
||||
extern void slb_initialize(void);
|
||||
|
||||
/*
|
||||
* Allocate segment tables for secondary CPUs. These must all go in
|
||||
* the first (bolted) segment, so that do_stab_bolted won't get a
|
||||
|
@ -243,18 +244,21 @@ void stabs_alloc(void)
|
|||
if (cpu == 0)
|
||||
continue; /* stab for CPU 0 is statically allocated */
|
||||
|
||||
newstab = lmb_alloc_base(PAGE_SIZE, PAGE_SIZE, 1<<SID_SHIFT);
|
||||
newstab = lmb_alloc_base(HW_PAGE_SIZE, HW_PAGE_SIZE,
|
||||
1<<SID_SHIFT);
|
||||
if (! newstab)
|
||||
panic("Unable to allocate segment table for CPU %d.\n",
|
||||
cpu);
|
||||
|
||||
newstab += KERNELBASE;
|
||||
|
||||
memset((void *)newstab, 0, PAGE_SIZE);
|
||||
memset((void *)newstab, 0, HW_PAGE_SIZE);
|
||||
|
||||
paca[cpu].stab_addr = newstab;
|
||||
paca[cpu].stab_real = virt_to_abs(newstab);
|
||||
printk(KERN_DEBUG "Segment table for CPU %d at 0x%lx virtual, 0x%lx absolute\n", cpu, paca[cpu].stab_addr, paca[cpu].stab_real);
|
||||
printk(KERN_DEBUG "Segment table for CPU %d at 0x%lx "
|
||||
"virtual, 0x%lx absolute\n",
|
||||
cpu, paca[cpu].stab_addr, paca[cpu].stab_real);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,13 +271,9 @@ void stab_initialize(unsigned long stab)
|
|||
{
|
||||
unsigned long vsid = get_kernel_vsid(KERNELBASE);
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_SLB)) {
|
||||
slb_initialize();
|
||||
} else {
|
||||
asm volatile("isync; slbia; isync":::"memory");
|
||||
make_ste(stab, GET_ESID(KERNELBASE), vsid);
|
||||
asm volatile("isync; slbia; isync":::"memory");
|
||||
make_ste(stab, GET_ESID(KERNELBASE), vsid);
|
||||
|
||||
/* Order update */
|
||||
asm volatile("sync":::"memory");
|
||||
}
|
||||
/* Order update */
|
||||
asm volatile("sync":::"memory");
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
|
@ -30,7 +31,7 @@
|
|||
#include <asm/pgalloc.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/tlb.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <asm/bug.h>
|
||||
|
||||
DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
|
||||
|
||||
|
@ -126,28 +127,46 @@ void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf)
|
|||
* (if we remove it we should clear the _PTE_HPTEFLAGS bits).
|
||||
*/
|
||||
void hpte_update(struct mm_struct *mm, unsigned long addr,
|
||||
unsigned long pte, int wrprot)
|
||||
pte_t *ptep, unsigned long pte, int huge)
|
||||
{
|
||||
struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
|
||||
unsigned long vsid;
|
||||
unsigned int psize = mmu_virtual_psize;
|
||||
int i;
|
||||
|
||||
i = batch->index;
|
||||
|
||||
/* We mask the address for the base page size. Huge pages will
|
||||
* have applied their own masking already
|
||||
*/
|
||||
addr &= PAGE_MASK;
|
||||
|
||||
/* Get page size (maybe move back to caller) */
|
||||
if (huge) {
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
psize = mmu_huge_psize;
|
||||
#else
|
||||
BUG();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* This can happen when we are in the middle of a TLB batch and
|
||||
* we encounter memory pressure (eg copy_page_range when it tries
|
||||
* to allocate a new pte). If we have to reclaim memory and end
|
||||
* up scanning and resetting referenced bits then our batch context
|
||||
* will change mid stream.
|
||||
*
|
||||
* We also need to ensure only one page size is present in a given
|
||||
* batch
|
||||
*/
|
||||
if (i != 0 && (mm != batch->mm || batch->large != pte_huge(pte))) {
|
||||
if (i != 0 && (mm != batch->mm || batch->psize != psize)) {
|
||||
flush_tlb_pending();
|
||||
i = 0;
|
||||
}
|
||||
if (i == 0) {
|
||||
batch->mm = mm;
|
||||
batch->large = pte_huge(pte);
|
||||
batch->psize = psize;
|
||||
}
|
||||
if (addr < KERNELBASE) {
|
||||
vsid = get_vsid(mm->context.id, addr);
|
||||
|
@ -155,7 +174,7 @@ void hpte_update(struct mm_struct *mm, unsigned long addr,
|
|||
} else
|
||||
vsid = get_kernel_vsid(addr);
|
||||
batch->vaddr[i] = (vsid << 28 ) | (addr & 0x0fffffff);
|
||||
batch->pte[i] = __pte(pte);
|
||||
batch->pte[i] = __real_pte(__pte(pte), ptep);
|
||||
batch->index = ++i;
|
||||
if (i >= PPC64_TLB_BATCH_NR)
|
||||
flush_tlb_pending();
|
||||
|
@ -177,7 +196,8 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
|
|||
local = 1;
|
||||
|
||||
if (i == 1)
|
||||
flush_hash_page(batch->vaddr[0], batch->pte[0], local);
|
||||
flush_hash_page(batch->vaddr[0], batch->pte[0],
|
||||
batch->psize, local);
|
||||
else
|
||||
flush_hash_range(i, local);
|
||||
batch->index = 0;
|
||||
|
|
|
@ -11,3 +11,4 @@ obj-$(CONFIG_85xx) += 85xx/
|
|||
obj-$(CONFIG_PPC_PSERIES) += pseries/
|
||||
obj-$(CONFIG_PPC_ISERIES) += iseries/
|
||||
obj-$(CONFIG_PPC_MAPLE) += maple/
|
||||
obj-$(CONFIG_PPC_CELL) += cell/
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
obj-y += interrupt.o iommu.o setup.o spider-pic.o
|
||||
obj-$(CONFIG_SMP) += smp.o
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* BPA Internal Interrupt Controller
|
||||
* Cell Internal Interrupt Controller
|
||||
*
|
||||
* (C) Copyright IBM Deutschland Entwicklung GmbH 2005
|
||||
*
|
||||
|
@ -31,7 +31,7 @@
|
|||
#include <asm/prom.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
#include "bpa_iic.h"
|
||||
#include "interrupt.h"
|
||||
|
||||
struct iic_pending_bits {
|
||||
u32 data;
|
||||
|
@ -89,7 +89,7 @@ static void iic_end(unsigned int irq)
|
|||
}
|
||||
|
||||
static struct hw_interrupt_type iic_pic = {
|
||||
.typename = " BPA-IIC ",
|
||||
.typename = " CELL-IIC ",
|
||||
.startup = iic_startup,
|
||||
.enable = iic_enable,
|
||||
.disable = iic_disable,
|
||||
|
@ -106,7 +106,7 @@ static int iic_external_get_irq(struct iic_pending_bits pending)
|
|||
irq = -1;
|
||||
|
||||
/*
|
||||
* This mapping is specific to the Broadband
|
||||
* This mapping is specific to the Cell Broadband
|
||||
* Engine. We might need to get the numbers
|
||||
* from the device tree to support future CPUs.
|
||||
*/
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef ASM_BPA_IIC_H
|
||||
#define ASM_BPA_IIC_H
|
||||
#ifndef ASM_CELL_PIC_H
|
||||
#define ASM_CELL_PIC_H
|
||||
#ifdef __KERNEL__
|
||||
/*
|
||||
* Mapping of IIC pending bits into per-node
|
||||
|
@ -21,7 +21,7 @@
|
|||
* + node number
|
||||
* * don't care
|
||||
*
|
||||
* A node consists of a Broadband Engine and an optional
|
||||
* A node consists of a Cell Broadband Engine and an optional
|
||||
* south bridge device providing a maximum of 64 IRQs.
|
||||
* The south bridge may be connected to either IOIF0
|
||||
* or IOIF1.
|
||||
|
@ -59,4 +59,4 @@ extern void spider_init_IRQ(void);
|
|||
extern int spider_get_irq(unsigned long int_pending);
|
||||
|
||||
#endif
|
||||
#endif /* ASM_BPA_IIC_H */
|
||||
#endif /* ASM_CELL_PIC_H */
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* IOMMU implementation for Broadband Processor Architecture
|
||||
* IOMMU implementation for Cell Broadband Processor Architecture
|
||||
* We just establish a linear mapping at boot by setting all the
|
||||
* IOPT cache entries in the CPU.
|
||||
* The mapping functions should be identical to pci_direct_iommu,
|
||||
|
@ -41,7 +41,7 @@
|
|||
#include <asm/system.h>
|
||||
#include <asm/ppc-pci.h>
|
||||
|
||||
#include "bpa_iommu.h"
|
||||
#include "iommu.h"
|
||||
|
||||
static inline unsigned long
|
||||
get_iopt_entry(unsigned long real_address, unsigned long ioid,
|
||||
|
@ -276,7 +276,7 @@ static void iommu_dev_setup_null(struct pci_dev *d) { }
|
|||
* for each DMA window used by any device. For now, we
|
||||
* happen to know that there is only one DMA window in use,
|
||||
* starting at iopt_phys_offset. */
|
||||
static void bpa_map_iommu(void)
|
||||
static void cell_map_iommu(void)
|
||||
{
|
||||
unsigned long address;
|
||||
void __iomem *base;
|
||||
|
@ -309,7 +309,7 @@ static void bpa_map_iommu(void)
|
|||
}
|
||||
|
||||
|
||||
static void *bpa_alloc_coherent(struct device *hwdev, size_t size,
|
||||
static void *cell_alloc_coherent(struct device *hwdev, size_t size,
|
||||
dma_addr_t *dma_handle, gfp_t flag)
|
||||
{
|
||||
void *ret;
|
||||
|
@ -317,65 +317,65 @@ static void *bpa_alloc_coherent(struct device *hwdev, size_t size,
|
|||
ret = (void *)__get_free_pages(flag, get_order(size));
|
||||
if (ret != NULL) {
|
||||
memset(ret, 0, size);
|
||||
*dma_handle = virt_to_abs(ret) | BPA_DMA_VALID;
|
||||
*dma_handle = virt_to_abs(ret) | CELL_DMA_VALID;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bpa_free_coherent(struct device *hwdev, size_t size,
|
||||
static void cell_free_coherent(struct device *hwdev, size_t size,
|
||||
void *vaddr, dma_addr_t dma_handle)
|
||||
{
|
||||
free_pages((unsigned long)vaddr, get_order(size));
|
||||
}
|
||||
|
||||
static dma_addr_t bpa_map_single(struct device *hwdev, void *ptr,
|
||||
static dma_addr_t cell_map_single(struct device *hwdev, void *ptr,
|
||||
size_t size, enum dma_data_direction direction)
|
||||
{
|
||||
return virt_to_abs(ptr) | BPA_DMA_VALID;
|
||||
return virt_to_abs(ptr) | CELL_DMA_VALID;
|
||||
}
|
||||
|
||||
static void bpa_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
|
||||
static void cell_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
|
||||
size_t size, enum dma_data_direction direction)
|
||||
{
|
||||
}
|
||||
|
||||
static int bpa_map_sg(struct device *hwdev, struct scatterlist *sg,
|
||||
static int cell_map_sg(struct device *hwdev, struct scatterlist *sg,
|
||||
int nents, enum dma_data_direction direction)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nents; i++, sg++) {
|
||||
sg->dma_address = (page_to_phys(sg->page) + sg->offset)
|
||||
| BPA_DMA_VALID;
|
||||
| CELL_DMA_VALID;
|
||||
sg->dma_length = sg->length;
|
||||
}
|
||||
|
||||
return nents;
|
||||
}
|
||||
|
||||
static void bpa_unmap_sg(struct device *hwdev, struct scatterlist *sg,
|
||||
static void cell_unmap_sg(struct device *hwdev, struct scatterlist *sg,
|
||||
int nents, enum dma_data_direction direction)
|
||||
{
|
||||
}
|
||||
|
||||
static int bpa_dma_supported(struct device *dev, u64 mask)
|
||||
static int cell_dma_supported(struct device *dev, u64 mask)
|
||||
{
|
||||
return mask < 0x100000000ull;
|
||||
}
|
||||
|
||||
void bpa_init_iommu(void)
|
||||
void cell_init_iommu(void)
|
||||
{
|
||||
bpa_map_iommu();
|
||||
cell_map_iommu();
|
||||
|
||||
/* Direct I/O, IOMMU off */
|
||||
ppc_md.iommu_dev_setup = iommu_dev_setup_null;
|
||||
ppc_md.iommu_bus_setup = iommu_bus_setup_null;
|
||||
|
||||
pci_dma_ops.alloc_coherent = bpa_alloc_coherent;
|
||||
pci_dma_ops.free_coherent = bpa_free_coherent;
|
||||
pci_dma_ops.map_single = bpa_map_single;
|
||||
pci_dma_ops.unmap_single = bpa_unmap_single;
|
||||
pci_dma_ops.map_sg = bpa_map_sg;
|
||||
pci_dma_ops.unmap_sg = bpa_unmap_sg;
|
||||
pci_dma_ops.dma_supported = bpa_dma_supported;
|
||||
pci_dma_ops.alloc_coherent = cell_alloc_coherent;
|
||||
pci_dma_ops.free_coherent = cell_free_coherent;
|
||||
pci_dma_ops.map_single = cell_map_single;
|
||||
pci_dma_ops.unmap_single = cell_unmap_single;
|
||||
pci_dma_ops.map_sg = cell_map_sg;
|
||||
pci_dma_ops.unmap_sg = cell_unmap_sg;
|
||||
pci_dma_ops.dma_supported = cell_dma_supported;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef BPA_IOMMU_H
|
||||
#define BPA_IOMMU_H
|
||||
#ifndef CELL_IOMMU_H
|
||||
#define CELL_IOMMU_H
|
||||
|
||||
/* some constants */
|
||||
enum {
|
||||
|
@ -55,11 +55,11 @@ enum {
|
|||
|
||||
/* The high bit needs to be set on every DMA address,
|
||||
only 2GB are addressable */
|
||||
BPA_DMA_VALID = 0x80000000,
|
||||
BPA_DMA_MASK = 0x7fffffff,
|
||||
CELL_DMA_VALID = 0x80000000,
|
||||
CELL_DMA_MASK = 0x7fffffff,
|
||||
};
|
||||
|
||||
|
||||
void bpa_init_iommu(void);
|
||||
void cell_init_iommu(void);
|
||||
|
||||
#endif
|
|
@ -1,11 +1,11 @@
|
|||
/*
|
||||
* linux/arch/ppc/kernel/bpa_setup.c
|
||||
* linux/arch/powerpc/platforms/cell/cell_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
|
||||
* Modified by BPA Team, IBM Deutschland Entwicklung GmbH
|
||||
* Modified by Cell Team, IBM Deutschland Entwicklung GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -46,8 +46,8 @@
|
|||
#include <asm/ppc-pci.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include "bpa_iic.h"
|
||||
#include "bpa_iommu.h"
|
||||
#include "interrupt.h"
|
||||
#include "iommu.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
|
@ -55,7 +55,7 @@
|
|||
#define DBG(fmt...)
|
||||
#endif
|
||||
|
||||
void bpa_show_cpuinfo(struct seq_file *m)
|
||||
void cell_show_cpuinfo(struct seq_file *m)
|
||||
{
|
||||
struct device_node *root;
|
||||
const char *model = "";
|
||||
|
@ -63,22 +63,22 @@ void bpa_show_cpuinfo(struct seq_file *m)
|
|||
root = of_find_node_by_path("/");
|
||||
if (root)
|
||||
model = get_property(root, "model", NULL);
|
||||
seq_printf(m, "machine\t\t: BPA %s\n", model);
|
||||
seq_printf(m, "machine\t\t: CHRP %s\n", model);
|
||||
of_node_put(root);
|
||||
}
|
||||
|
||||
static void bpa_progress(char *s, unsigned short hex)
|
||||
static void cell_progress(char *s, unsigned short hex)
|
||||
{
|
||||
printk("*** %04x : %s\n", hex, s ? s : "");
|
||||
}
|
||||
|
||||
static void __init bpa_setup_arch(void)
|
||||
static void __init cell_setup_arch(void)
|
||||
{
|
||||
ppc_md.init_IRQ = iic_init_IRQ;
|
||||
ppc_md.get_irq = iic_get_irq;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
smp_init_pSeries();
|
||||
smp_init_cell();
|
||||
#endif
|
||||
|
||||
/* init to some ~sane value until calibrate_delay() runs */
|
||||
|
@ -97,39 +97,39 @@ static void __init bpa_setup_arch(void)
|
|||
conswitchp = &dummy_con;
|
||||
#endif
|
||||
|
||||
bpa_nvram_init();
|
||||
mmio_nvram_init();
|
||||
}
|
||||
|
||||
/*
|
||||
* Early initialization. Relocation is on but do not reference unbolted pages
|
||||
*/
|
||||
static void __init bpa_init_early(void)
|
||||
static void __init cell_init_early(void)
|
||||
{
|
||||
DBG(" -> bpa_init_early()\n");
|
||||
DBG(" -> cell_init_early()\n");
|
||||
|
||||
hpte_init_native();
|
||||
|
||||
bpa_init_iommu();
|
||||
cell_init_iommu();
|
||||
|
||||
ppc64_interrupt_controller = IC_BPA_IIC;
|
||||
ppc64_interrupt_controller = IC_CELL_PIC;
|
||||
|
||||
DBG(" <- bpa_init_early()\n");
|
||||
DBG(" <- cell_init_early()\n");
|
||||
}
|
||||
|
||||
|
||||
static int __init bpa_probe(int platform)
|
||||
static int __init cell_probe(int platform)
|
||||
{
|
||||
if (platform != PLATFORM_BPA)
|
||||
if (platform != PLATFORM_CELL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct machdep_calls __initdata bpa_md = {
|
||||
.probe = bpa_probe,
|
||||
.setup_arch = bpa_setup_arch,
|
||||
.init_early = bpa_init_early,
|
||||
.show_cpuinfo = bpa_show_cpuinfo,
|
||||
struct machdep_calls __initdata cell_md = {
|
||||
.probe = cell_probe,
|
||||
.setup_arch = cell_setup_arch,
|
||||
.init_early = cell_init_early,
|
||||
.show_cpuinfo = cell_show_cpuinfo,
|
||||
.restart = rtas_restart,
|
||||
.power_off = rtas_power_off,
|
||||
.halt = rtas_halt,
|
||||
|
@ -137,5 +137,5 @@ struct machdep_calls __initdata bpa_md = {
|
|||
.get_rtc_time = rtas_get_rtc_time,
|
||||
.set_rtc_time = rtas_set_rtc_time,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = bpa_progress,
|
||||
.progress = cell_progress,
|
||||
};
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* SMP support for BPA machines.
|
||||
*
|
||||
* Dave Engebretsen, Peter Bergner, and
|
||||
* Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
|
||||
*
|
||||
* Plus various changes from other IBM teams...
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/cache.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/cpu.h>
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/paca.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/rtas.h>
|
||||
|
||||
#include "interrupt.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
#else
|
||||
#define DBG(fmt...)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The primary thread of each non-boot processor is recorded here before
|
||||
* smp init.
|
||||
*/
|
||||
static cpumask_t of_spin_map;
|
||||
|
||||
extern void pSeries_secondary_smp_init(unsigned long);
|
||||
|
||||
/**
|
||||
* smp_startup_cpu() - start the given cpu
|
||||
*
|
||||
* At boot time, there is nothing to do for primary threads which were
|
||||
* started from Open Firmware. For anything else, call RTAS with the
|
||||
* appropriate start location.
|
||||
*
|
||||
* Returns:
|
||||
* 0 - failure
|
||||
* 1 - success
|
||||
*/
|
||||
static inline int __devinit smp_startup_cpu(unsigned int lcpu)
|
||||
{
|
||||
int status;
|
||||
unsigned long start_here = __pa((u32)*((unsigned long *)
|
||||
pSeries_secondary_smp_init));
|
||||
unsigned int pcpu;
|
||||
int start_cpu;
|
||||
|
||||
if (cpu_isset(lcpu, of_spin_map))
|
||||
/* Already started by OF and sitting in spin loop */
|
||||
return 1;
|
||||
|
||||
pcpu = get_hard_smp_processor_id(lcpu);
|
||||
|
||||
/* Fixup atomic count: it exited inside IRQ handler. */
|
||||
paca[lcpu].__current->thread_info->preempt_count = 0;
|
||||
|
||||
/*
|
||||
* If the RTAS start-cpu token does not exist then presume the
|
||||
* cpu is already spinning.
|
||||
*/
|
||||
start_cpu = rtas_token("start-cpu");
|
||||
if (start_cpu == RTAS_UNKNOWN_SERVICE)
|
||||
return 1;
|
||||
|
||||
status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, lcpu);
|
||||
if (status != 0) {
|
||||
printk(KERN_ERR "start-cpu failed: %i\n", status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void smp_iic_message_pass(int target, int msg)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (target < NR_CPUS) {
|
||||
iic_cause_IPI(target, msg);
|
||||
} else {
|
||||
for_each_online_cpu(i) {
|
||||
if (target == MSG_ALL_BUT_SELF
|
||||
&& i == smp_processor_id())
|
||||
continue;
|
||||
iic_cause_IPI(i, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int __init smp_iic_probe(void)
|
||||
{
|
||||
iic_request_IPIs();
|
||||
|
||||
return cpus_weight(cpu_possible_map);
|
||||
}
|
||||
|
||||
static void __devinit smp_iic_setup_cpu(int cpu)
|
||||
{
|
||||
if (cpu != boot_cpuid)
|
||||
iic_setup_cpu();
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(timebase_lock);
|
||||
static unsigned long timebase = 0;
|
||||
|
||||
static void __devinit cell_give_timebase(void)
|
||||
{
|
||||
spin_lock(&timebase_lock);
|
||||
rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
|
||||
timebase = get_tb();
|
||||
spin_unlock(&timebase_lock);
|
||||
|
||||
while (timebase)
|
||||
barrier();
|
||||
rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
|
||||
}
|
||||
|
||||
static void __devinit cell_take_timebase(void)
|
||||
{
|
||||
while (!timebase)
|
||||
barrier();
|
||||
spin_lock(&timebase_lock);
|
||||
set_tb(timebase >> 32, timebase & 0xffffffff);
|
||||
timebase = 0;
|
||||
spin_unlock(&timebase_lock);
|
||||
}
|
||||
|
||||
static void __devinit smp_cell_kick_cpu(int nr)
|
||||
{
|
||||
BUG_ON(nr < 0 || nr >= NR_CPUS);
|
||||
|
||||
if (!smp_startup_cpu(nr))
|
||||
return;
|
||||
|
||||
/*
|
||||
* The processor is currently spinning, waiting for the
|
||||
* cpu_start field to become non-zero After we set cpu_start,
|
||||
* the processor will continue on to secondary_start
|
||||
*/
|
||||
paca[nr].cpu_start = 1;
|
||||
}
|
||||
|
||||
static int smp_cell_cpu_bootable(unsigned int nr)
|
||||
{
|
||||
/* Special case - we inhibit secondary thread startup
|
||||
* during boot if the user requests it. Odd-numbered
|
||||
* cpus are assumed to be secondary threads.
|
||||
*/
|
||||
if (system_state < SYSTEM_RUNNING &&
|
||||
cpu_has_feature(CPU_FTR_SMT) &&
|
||||
!smt_enabled_at_boot && nr % 2 != 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
static struct smp_ops_t bpa_iic_smp_ops = {
|
||||
.message_pass = smp_iic_message_pass,
|
||||
.probe = smp_iic_probe,
|
||||
.kick_cpu = smp_cell_kick_cpu,
|
||||
.setup_cpu = smp_iic_setup_cpu,
|
||||
.cpu_bootable = smp_cell_cpu_bootable,
|
||||
};
|
||||
|
||||
/* This is called very early */
|
||||
void __init smp_init_cell(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
DBG(" -> smp_init_cell()\n");
|
||||
|
||||
smp_ops = &bpa_iic_smp_ops;
|
||||
|
||||
/* Mark threads which are still spinning in hold loops. */
|
||||
if (cpu_has_feature(CPU_FTR_SMT)) {
|
||||
for_each_present_cpu(i) {
|
||||
if (i % 2 == 0)
|
||||
/*
|
||||
* Even-numbered logical cpus correspond to
|
||||
* primary threads.
|
||||
*/
|
||||
cpu_set(i, of_spin_map);
|
||||
}
|
||||
} else {
|
||||
of_spin_map = cpu_present_map;
|
||||
}
|
||||
|
||||
cpu_clear(boot_cpuid, of_spin_map);
|
||||
|
||||
/* Non-lpar has additional take/give timebase */
|
||||
if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
|
||||
smp_ops->give_timebase = cell_give_timebase;
|
||||
smp_ops->take_timebase = cell_take_timebase;
|
||||
}
|
||||
|
||||
DBG(" <- smp_init_cell()\n");
|
||||
}
|
|
@ -27,7 +27,7 @@
|
|||
#include <asm/prom.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "bpa_iic.h"
|
||||
#include "interrupt.h"
|
||||
|
||||
/* register layout taken from Spider spec, table 7.4-4 */
|
||||
enum {
|
|
@ -17,6 +17,7 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/rtas.h>
|
||||
#include "chrp.h"
|
||||
|
||||
static unsigned int nvram_size;
|
||||
|
@ -25,7 +26,8 @@ static DEFINE_SPINLOCK(nvram_lock);
|
|||
|
||||
static unsigned char chrp_nvram_read(int addr)
|
||||
{
|
||||
unsigned long done, flags;
|
||||
unsigned int done;
|
||||
unsigned long flags;
|
||||
unsigned char ret;
|
||||
|
||||
if (addr >= nvram_size) {
|
||||
|
@ -34,7 +36,8 @@ static unsigned char chrp_nvram_read(int addr)
|
|||
return 0xff;
|
||||
}
|
||||
spin_lock_irqsave(&nvram_lock, flags);
|
||||
if ((call_rtas("nvram-fetch", 3, 2, &done, addr, __pa(nvram_buf), 1) != 0) || 1 != done)
|
||||
if ((rtas_call(rtas_token("nvram-fetch"), 3, 2, &done, addr,
|
||||
__pa(nvram_buf), 1) != 0) || 1 != done)
|
||||
ret = 0xff;
|
||||
else
|
||||
ret = nvram_buf[0];
|
||||
|
@ -45,7 +48,8 @@ static unsigned char chrp_nvram_read(int addr)
|
|||
|
||||
static void chrp_nvram_write(int addr, unsigned char val)
|
||||
{
|
||||
unsigned long done, flags;
|
||||
unsigned int done;
|
||||
unsigned long flags;
|
||||
|
||||
if (addr >= nvram_size) {
|
||||
printk(KERN_DEBUG "%s: write addr %d > nvram_size %u\n",
|
||||
|
@ -54,7 +58,8 @@ static void chrp_nvram_write(int addr, unsigned char val)
|
|||
}
|
||||
spin_lock_irqsave(&nvram_lock, flags);
|
||||
nvram_buf[0] = val;
|
||||
if ((call_rtas("nvram-store", 3, 2, &done, addr, __pa(nvram_buf), 1) != 0) || 1 != done)
|
||||
if ((rtas_call(rtas_token("nvram-store"), 3, 2, &done, addr,
|
||||
__pa(nvram_buf), 1) != 0) || 1 != done)
|
||||
printk(KERN_DEBUG "rtas IO error storing 0x%02x at %d", val, addr);
|
||||
spin_unlock_irqrestore(&nvram_lock, flags);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mv643xx.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
|
|
|
@ -35,43 +35,6 @@
|
|||
#include <asm/smp.h>
|
||||
#include <asm/mpic.h>
|
||||
|
||||
extern unsigned long smp_chrp_cpu_nr;
|
||||
|
||||
static int __init smp_chrp_probe(void)
|
||||
{
|
||||
struct device_node *cpus = NULL;
|
||||
unsigned int *reg;
|
||||
int reglen;
|
||||
int ncpus = 0;
|
||||
int cpuid;
|
||||
unsigned int phys;
|
||||
|
||||
/* Count CPUs in the device-tree */
|
||||
cpuid = 1; /* the boot cpu is logical cpu 0 */
|
||||
while ((cpus = of_find_node_by_type(cpus, "cpu")) != NULL) {
|
||||
phys = ncpus;
|
||||
reg = (unsigned int *) get_property(cpus, "reg", ®len);
|
||||
if (reg && reglen >= sizeof(unsigned int))
|
||||
/* hmmm, not having a reg property would be bad */
|
||||
phys = *reg;
|
||||
if (phys != boot_cpuid_phys) {
|
||||
set_hard_smp_processor_id(cpuid, phys);
|
||||
++cpuid;
|
||||
}
|
||||
++ncpus;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "CHRP SMP probe found %d cpus\n", ncpus);
|
||||
|
||||
/* Nothing more to do if less than 2 of them */
|
||||
if (ncpus <= 1)
|
||||
return 1;
|
||||
|
||||
mpic_request_ipis();
|
||||
|
||||
return ncpus;
|
||||
}
|
||||
|
||||
static void __devinit smp_chrp_kick_cpu(int nr)
|
||||
{
|
||||
*(unsigned long *)KERNELBASE = nr;
|
||||
|
@ -114,7 +77,7 @@ void __devinit smp_chrp_take_timebase(void)
|
|||
/* CHRP with openpic */
|
||||
struct smp_ops_t chrp_smp_ops = {
|
||||
.message_pass = smp_mpic_message_pass,
|
||||
.probe = smp_chrp_probe,
|
||||
.probe = smp_mpic_probe,
|
||||
.kick_cpu = smp_chrp_kick_cpu,
|
||||
.setup_cpu = smp_chrp_setup_cpu,
|
||||
.give_timebase = smp_chrp_give_timebase,
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
* drive the hypervisor from the OS.
|
||||
*/
|
||||
|
||||
#include <asm/iSeries/HvCallSc.h>
|
||||
#include <asm/iSeries/HvTypes.h>
|
||||
#include <asm/iseries/hv_call_sc.h>
|
||||
#include <asm/iseries/hv_types.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
#define HvCallHptGetHptAddress HvCallHpt + 0
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
#ifndef _PLATFORMS_ISERIES_CALL_PCI_H
|
||||
#define _PLATFORMS_ISERIES_CALL_PCI_H
|
||||
|
||||
#include <asm/iSeries/HvCallSc.h>
|
||||
#include <asm/iSeries/HvTypes.h>
|
||||
#include <asm/iseries/hv_call_sc.h>
|
||||
#include <asm/iseries/hv_types.h>
|
||||
|
||||
/*
|
||||
* DSA == Direct Select Address
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
* drive the hypervisor from the OS.
|
||||
*/
|
||||
|
||||
#include <asm/iSeries/HvCallSc.h>
|
||||
#include <asm/iSeries/HvTypes.h>
|
||||
#include <asm/iseries/hv_call_sc.h>
|
||||
#include <asm/iseries/hv_types.h>
|
||||
|
||||
#define HvCallSmGet64BitsOfAccessMap HvCallSm + 11
|
||||
|
||||
|
|
|
@ -39,15 +39,16 @@ static inline void iSeries_hunlock(unsigned long slot)
|
|||
spin_unlock(&iSeries_hlocks[(slot >> 4) & 0x3f]);
|
||||
}
|
||||
|
||||
static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
|
||||
unsigned long prpn, unsigned long vflags,
|
||||
unsigned long rflags)
|
||||
long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
|
||||
unsigned long pa, unsigned long rflags,
|
||||
unsigned long vflags, int psize)
|
||||
{
|
||||
unsigned long arpn;
|
||||
long slot;
|
||||
hpte_t lhpte;
|
||||
int secondary = 0;
|
||||
|
||||
BUG_ON(psize != MMU_PAGE_4K);
|
||||
|
||||
/*
|
||||
* The hypervisor tries both primary and secondary.
|
||||
* If we are being called to insert in the secondary,
|
||||
|
@ -59,8 +60,19 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
|
|||
|
||||
iSeries_hlock(hpte_group);
|
||||
|
||||
slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT);
|
||||
BUG_ON(lhpte.v & HPTE_V_VALID);
|
||||
slot = HvCallHpt_findValid(&lhpte, va >> HW_PAGE_SHIFT);
|
||||
if (unlikely(lhpte.v & HPTE_V_VALID)) {
|
||||
if (vflags & HPTE_V_BOLTED) {
|
||||
HvCallHpt_setSwBits(slot, 0x10, 0);
|
||||
HvCallHpt_setPp(slot, PP_RWXX);
|
||||
iSeries_hunlock(hpte_group);
|
||||
if (slot < 0)
|
||||
return 0x8 | (slot & 7);
|
||||
else
|
||||
return slot & 7;
|
||||
}
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (slot == -1) { /* No available entry found in either group */
|
||||
iSeries_hunlock(hpte_group);
|
||||
|
@ -73,10 +85,9 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
|
|||
slot &= 0x7fffffffffffffff;
|
||||
}
|
||||
|
||||
arpn = phys_to_abs(prpn << PAGE_SHIFT) >> PAGE_SHIFT;
|
||||
|
||||
lhpte.v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID;
|
||||
lhpte.r = (arpn << HPTE_R_RPN_SHIFT) | rflags;
|
||||
lhpte.v = hpte_encode_v(va, MMU_PAGE_4K) | vflags | HPTE_V_VALID;
|
||||
lhpte.r = hpte_encode_r(phys_to_abs(pa), MMU_PAGE_4K) | rflags;
|
||||
|
||||
/* Now fill in the actual HPTE */
|
||||
HvCallHpt_addValidate(slot, secondary, &lhpte);
|
||||
|
@ -86,25 +97,6 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
|
|||
return (secondary << 3) | (slot & 7);
|
||||
}
|
||||
|
||||
long iSeries_hpte_bolt_or_insert(unsigned long hpte_group,
|
||||
unsigned long va, unsigned long prpn, unsigned long vflags,
|
||||
unsigned long rflags)
|
||||
{
|
||||
long slot;
|
||||
hpte_t lhpte;
|
||||
|
||||
slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT);
|
||||
|
||||
if (lhpte.v & HPTE_V_VALID) {
|
||||
/* Bolt the existing HPTE */
|
||||
HvCallHpt_setSwBits(slot, 0x10, 0);
|
||||
HvCallHpt_setPp(slot, PP_RWXX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iSeries_hpte_insert(hpte_group, va, prpn, vflags, rflags);
|
||||
}
|
||||
|
||||
static unsigned long iSeries_hpte_getword0(unsigned long slot)
|
||||
{
|
||||
hpte_t hpte;
|
||||
|
@ -150,15 +142,17 @@ static long iSeries_hpte_remove(unsigned long hpte_group)
|
|||
* bits 61..63 : PP2,PP1,PP0
|
||||
*/
|
||||
static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
|
||||
unsigned long va, int large, int local)
|
||||
unsigned long va, int psize, int local)
|
||||
{
|
||||
hpte_t hpte;
|
||||
unsigned long avpn = va >> 23;
|
||||
unsigned long want_v;
|
||||
|
||||
iSeries_hlock(slot);
|
||||
|
||||
HvCallHpt_get(&hpte, slot);
|
||||
if ((HPTE_V_AVPN_VAL(hpte.v) == avpn) && (hpte.v & HPTE_V_VALID)) {
|
||||
want_v = hpte_encode_v(va, MMU_PAGE_4K);
|
||||
|
||||
if (HPTE_V_COMPARE(hpte.v, want_v) && (hpte.v & HPTE_V_VALID)) {
|
||||
/*
|
||||
* Hypervisor expects bits as NPPP, which is
|
||||
* different from how they are mapped in our PP.
|
||||
|
@ -210,14 +204,17 @@ static long iSeries_hpte_find(unsigned long vpn)
|
|||
*
|
||||
* No need to lock here because we should be the only user.
|
||||
*/
|
||||
static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea)
|
||||
static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
|
||||
int psize)
|
||||
{
|
||||
unsigned long vsid,va,vpn;
|
||||
long slot;
|
||||
|
||||
BUG_ON(psize != MMU_PAGE_4K);
|
||||
|
||||
vsid = get_kernel_vsid(ea);
|
||||
va = (vsid << 28) | (ea & 0x0fffffff);
|
||||
vpn = va >> PAGE_SHIFT;
|
||||
vpn = va >> HW_PAGE_SHIFT;
|
||||
slot = iSeries_hpte_find(vpn);
|
||||
if (slot == -1)
|
||||
panic("updateboltedpp: Could not find page to bolt\n");
|
||||
|
@ -225,7 +222,7 @@ static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea)
|
|||
}
|
||||
|
||||
static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va,
|
||||
int large, int local)
|
||||
int psize, int local)
|
||||
{
|
||||
unsigned long hpte_v;
|
||||
unsigned long avpn = va >> 23;
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
|
||||
#include <asm/page.h>
|
||||
#include <asm/abs_addr.h>
|
||||
#include <asm/iSeries/HvCall.h>
|
||||
#include <asm/iSeries/HvCallSc.h>
|
||||
#include <asm/iSeries/HvTypes.h>
|
||||
#include <asm/iseries/hv_call.h>
|
||||
#include <asm/iseries/hv_call_sc.h>
|
||||
#include <asm/iseries/hv_types.h>
|
||||
|
||||
|
||||
void HvCall_writeLogBuffer(const void *buffer, u64 len)
|
||||
|
@ -22,7 +22,7 @@ void HvCall_writeLogBuffer(const void *buffer, u64 len)
|
|||
|
||||
while (len) {
|
||||
hv_buf.addr = cur;
|
||||
left_this_page = ((cur & PAGE_MASK) + PAGE_SIZE) - cur;
|
||||
left_this_page = ((cur & HW_PAGE_MASK) + HW_PAGE_SIZE) - cur;
|
||||
if (left_this_page > len)
|
||||
left_this_page = len;
|
||||
hv_buf.len = left_this_page;
|
||||
|
@ -30,6 +30,6 @@ void HvCall_writeLogBuffer(const void *buffer, u64 len)
|
|||
HvCall2(HvCallBaseWriteLogBuffer,
|
||||
virt_to_abs(&hv_buf),
|
||||
left_this_page);
|
||||
cur = (cur & PAGE_MASK) + PAGE_SIZE;
|
||||
cur = (cur & HW_PAGE_MASK) + HW_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <asm/iSeries/HvLpConfig.h>
|
||||
#include <asm/iseries/hv_lp_config.h>
|
||||
|
||||
HvLpIndex HvLpConfig_getLpIndex_outline(void)
|
||||
{
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue