提交 1b17366d 编写于 作者: L Linus Torvalds

Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc

Pull powerpc updates from Ben Herrenschmidt:
 "So here's my next branch for powerpc.  A bit late as I was on vacation
  last week.  It's mostly the same stuff that was in next already, I
  just added two patches today which are the wiring up of lockref for
  powerpc, which for some reason fell through the cracks last time and
  is trivial.

  The highlights are, in addition to a bunch of bug fixes:

   - Reworked Machine Check handling on kernels running without a
     hypervisor (or acting as a hypervisor).  Provides hooks to handle
     some errors in real mode such as TLB errors, handle SLB errors,
     etc...

   - Support for retrieving memory error information from the service
     processor on IBM servers running without a hypervisor and routing
     them to the memory poison infrastructure.

   - _PAGE_NUMA support on server processors

   - 32-bit BookE relocatable kernel support

   - FSL e6500 hardware tablewalk support

   - A bunch of new/revived board support

   - FSL e6500 deeper idle states and altivec powerdown support

  You'll notice a generic mm change here, it has been acked by the
  relevant authorities and is a pre-req for our _PAGE_NUMA support"

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (121 commits)
  powerpc: Implement arch_spin_is_locked() using arch_spin_value_unlocked()
  powerpc: Add support for the optimised lockref implementation
  powerpc/powernv: Call OPAL sync before kexec'ing
  powerpc/eeh: Escalate error on non-existing PE
  powerpc/eeh: Handle multiple EEH errors
  powerpc: Fix transactional FP/VMX/VSX unavailable handlers
  powerpc: Don't corrupt transactional state when using FP/VMX in kernel
  powerpc: Reclaim two unused thread_info flag bits
  powerpc: Fix races with irq_work
  Move precessing of MCE queued event out from syscall exit path.
  pseries/cpuidle: Remove redundant call to ppc64_runlatch_off() in cpu idle routines
  powerpc: Make add_system_ram_resources() __init
  powerpc: add SATA_MV to ppc64_defconfig
  powerpc/powernv: Increase candidate fw image size
  powerpc: Add debug checks to catch invalid cpu-to-node mappings
  powerpc: Fix the setup of CPU-to-Node mappings during CPU online
  powerpc/iommu: Don't detach device without IOMMU group
  powerpc/eeh: Hotplug improvement
  powerpc/eeh: Call opal_pci_reinit() on powernv for restoring config space
  powerpc/eeh: Add restore_config operation
  ...
* Solomon SSD1289 Framebuffer Driver
Required properties:
- compatible: Should be "solomon,ssd1289fb". The only supported bus for
now is lbc.
- reg: Should contain address of the controller on the LBC bus. The detail
was described in Documentation/devicetree/bindings/powerpc/fsl/lbc.txt
Examples:
display@2,0 {
compatible = "solomon,ssd1289fb";
reg = <0x2 0x0000 0x0004>;
};
......@@ -140,6 +140,7 @@ config PPC
select OLD_SIGACTION if PPC32
select HAVE_DEBUG_STACKOVERFLOW
select HAVE_IRQ_EXIT_ON_IRQ_STACK
select ARCH_USE_CMPXCHG_LOCKREF if PPC64
config GENERIC_CSUM
def_bool CPU_LITTLE_ENDIAN
......@@ -214,9 +215,6 @@ config DEFAULT_UIMAGE
Used to allow a board to specify it wants a uImage built by default
default n
config REDBOOT
bool
config ARCH_HIBERNATION_POSSIBLE
bool
default y
......@@ -384,6 +382,12 @@ config ARCH_HAS_WALK_MEMORY
config ARCH_ENABLE_MEMORY_HOTREMOVE
def_bool y
config PPC64_SUPPORTS_MEMORY_FAILURE
bool "Add support for memory hwpoison"
depends on PPC_BOOK3S_64
default "y" if PPC_POWERNV
select ARCH_SUPPORTS_MEMORY_FAILURE
config KEXEC
bool "kexec system call"
depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP))
......@@ -404,8 +408,7 @@ config KEXEC
config CRASH_DUMP
bool "Build a kdump crash kernel"
depends on PPC64 || 6xx || FSL_BOOKE || (44x && !SMP)
select RELOCATABLE if PPC64 || 44x
select DYNAMIC_MEMSTART if FSL_BOOKE
select RELOCATABLE if PPC64 || 44x || FSL_BOOKE
help
Build a kernel suitable for use as a kdump capture kernel.
The same kernel binary can be used as production kernel and dump
......@@ -886,7 +889,7 @@ config DYNAMIC_MEMSTART
config RELOCATABLE
bool "Build a relocatable kernel"
depends on ADVANCED_OPTIONS && FLATMEM && 44x
depends on ADVANCED_OPTIONS && FLATMEM && (44x || FSL_BOOKE)
select NONSTATIC_KERNEL
help
This builds a kernel image that is capable of running at the
......
......@@ -16,6 +16,7 @@ mktree
uImage
cuImage.*
dtbImage.*
*.dtb
treeImage.*
zImage
zImage.initrd
......
......@@ -71,9 +71,9 @@ src-wlib-y := string.S crt0.S crtsavres.S stdio.c main.c \
uartlite.c mpc52xx-psc.c
src-wlib-$(CONFIG_40x) += 4xx.c planetcore.c
src-wlib-$(CONFIG_44x) += 4xx.c ebony.c bamboo.c
src-wlib-$(CONFIG_8xx) += mpc8xx.c planetcore.c
src-wlib-$(CONFIG_8xx) += mpc8xx.c planetcore.c fsl-soc.c
src-wlib-$(CONFIG_PPC_82xx) += pq2.c fsl-soc.c planetcore.c
src-wlib-$(CONFIG_EMBEDDED6xx) += mv64x60.c mv64x60_i2c.c ugecon.c
src-wlib-$(CONFIG_EMBEDDED6xx) += mv64x60.c mv64x60_i2c.c ugecon.c fsl-soc.c
src-plat-y := of.c epapr.c
src-plat-$(CONFIG_40x) += fixed-head.S ep405.c cuboot-hotfoot.c \
......@@ -95,7 +95,7 @@ src-plat-$(CONFIG_FSL_SOC_BOOKE) += cuboot-85xx.c cuboot-85xx-cpm2.c
src-plat-$(CONFIG_EMBEDDED6xx) += cuboot-pq2.c cuboot-mpc7448hpc2.c \
cuboot-c2k.c gamecube-head.S \
gamecube.c wii-head.S wii.c holly.c \
prpmc2800.c
prpmc2800.c fixed-head.S mvme5100.c
src-plat-$(CONFIG_AMIGAONE) += cuboot-amigaone.c
src-plat-$(CONFIG_PPC_PS3) += ps3-head.S ps3-hvcall.S ps3.c
src-plat-$(CONFIG_EPAPR_BOOT) += epapr.c epapr-wrapper.c
......@@ -286,6 +286,7 @@ image-$(CONFIG_MPC7448HPC2) += cuImage.mpc7448hpc2
image-$(CONFIG_PPC_C2K) += cuImage.c2k
image-$(CONFIG_GAMECUBE) += dtbImage.gamecube
image-$(CONFIG_WII) += dtbImage.wii
image-$(CONFIG_MVME5100) += dtbImage.mvme5100
# Board port in arch/powerpc/platform/amigaone/Kconfig
image-$(CONFIG_AMIGAONE) += cuImage.amigaone
......
/*
* QorIQ Elo3 DMA device tree stub [ controller @ offset 0x102300 ]
*
* Copyright 2013 Freescale Semiconductor Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions 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.
* * Neither the name of Freescale Semiconductor nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") as published by the Free Software
* Foundation, either version 2 of that License or (at your option) any
* later version.
*
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
*/
dma2: dma@102300 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "fsl,elo3-dma";
reg = <0x102300 0x4>,
<0x102600 0x4>;
ranges = <0x0 0x102100 0x500>;
dma-channel@0 {
compatible = "fsl,eloplus-dma-channel";
reg = <0x0 0x80>;
interrupts = <464 2 0 0>;
};
dma-channel@80 {
compatible = "fsl,eloplus-dma-channel";
reg = <0x80 0x80>;
interrupts = <465 2 0 0>;
};
dma-channel@100 {
compatible = "fsl,eloplus-dma-channel";
reg = <0x100 0x80>;
interrupts = <466 2 0 0>;
};
dma-channel@180 {
compatible = "fsl,eloplus-dma-channel";
reg = <0x180 0x80>;
interrupts = <467 2 0 0>;
};
dma-channel@300 {
compatible = "fsl,eloplus-dma-channel";
reg = <0x300 0x80>;
interrupts = <468 2 0 0>;
};
dma-channel@380 {
compatible = "fsl,eloplus-dma-channel";
reg = <0x380 0x80>;
interrupts = <469 2 0 0>;
};
dma-channel@400 {
compatible = "fsl,eloplus-dma-channel";
reg = <0x400 0x80>;
interrupts = <470 2 0 0>;
};
dma-channel@480 {
compatible = "fsl,eloplus-dma-channel";
reg = <0x480 0x80>;
interrupts = <471 2 0 0>;
};
};
......@@ -36,7 +36,8 @@
#address-cells = <2>;
#size-cells = <1>;
compatible = "fsl,p1020-elbc", "fsl,elbc", "simple-bus";
interrupts = <19 2 0 0>;
interrupts = <19 2 0 0>,
<16 2 0 0>;
};
/* controller at 0x9000 */
......
......@@ -36,7 +36,8 @@
#address-cells = <2>;
#size-cells = <1>;
compatible = "fsl,p1021-elbc", "fsl,elbc", "simple-bus";
interrupts = <19 2 0 0>;
interrupts = <19 2 0 0>,
<16 2 0 0>;
};
/* controller at 0x9000 */
......
......@@ -40,7 +40,8 @@
* pin muxing when the DIU is enabled.
*/
compatible = "fsl,p1022-elbc", "fsl,elbc";
interrupts = <19 2 0 0>;
interrupts = <19 2 0 0>,
<16 2 0 0>;
};
/* controller at 0x9000 */
......
......@@ -36,7 +36,8 @@
#address-cells = <2>;
#size-cells = <1>;
compatible = "fsl,p1023-elbc", "fsl,elbc", "simple-bus";
interrupts = <19 2 0 0>;
interrupts = <19 2 0 0>,
<16 2 0 0>;
};
/* controller at 0xa000 */
......
......@@ -406,7 +406,7 @@
MSI: ppc4xx-msi@C10000000 {
compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
reg = < 0x0 0xEF620000 0x100>;
reg = <0xEF620000 0x100>;
sdr-base = <0x4B0>;
msi-data = <0x00000000>;
msi-mask = <0x44440000>;
......
/*
* Device Tree Source for Motorola/Emerson MVME5100.
*
* Copyright 2013 CSC Australia Pty. Ltd.
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without
* any warranty of any kind, whether express or implied.
*/
/dts-v1/;
/ {
model = "MVME5100";
compatible = "MVME5100";
#address-cells = <1>;
#size-cells = <1>;
aliases {
serial0 = &serial0;
pci0 = &pci0;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
PowerPC,7410 {
device_type = "cpu";
reg = <0x0>;
/* Following required by dtc but not used */
d-cache-line-size = <32>;
i-cache-line-size = <32>;
i-cache-size = <32768>;
d-cache-size = <32768>;
timebase-frequency = <25000000>;
clock-frequency = <500000000>;
bus-frequency = <100000000>;
};
};
memory {
device_type = "memory";
reg = <0x0 0x20000000>;
};
hawk@fef80000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "hawk-bridge", "simple-bus";
ranges = <0x0 0xfef80000 0x10000>;
reg = <0xfef80000 0x10000>;
serial0: serial@8000 {
device_type = "serial";
compatible = "ns16550";
reg = <0x8000 0x80>;
reg-shift = <4>;
clock-frequency = <1843200>;
current-speed = <9600>;
interrupts = <1 1>; // IRQ1 Level Active Low.
interrupt-parent = <&mpic>;
};
serial1: serial@8200 {
device_type = "serial";
compatible = "ns16550";
reg = <0x8200 0x80>;
reg-shift = <4>;
clock-frequency = <1843200>;
current-speed = <9600>;
interrupts = <1 1>; // IRQ1 Level Active Low.
interrupt-parent = <&mpic>;
};
mpic: interrupt-controller@f3f80000 {
#interrupt-cells = <2>;
#address-cells = <0>;
device_type = "open-pic";
compatible = "chrp,open-pic";
interrupt-controller;
reg = <0xf3f80000 0x40000>;
};
};
pci0: pci@feff0000 {
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
device_type = "pci";
compatible = "hawk-pci";
reg = <0xfec00000 0x400000>;
8259-interrupt-acknowledge = <0xfeff0030>;
ranges = <0x1000000 0x0 0x0 0xfe000000 0x0 0x800000
0x2000000 0x0 0x80000000 0x80000000 0x0 0x74000000>;
bus-range = <0 255>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/*
* This definition (IDSEL 11) duplicates the
* interrupts definition in the i8259
* interrupt controller below.
*
* Do not change the interrupt sense/polarity from
* 0x2 to anything else, doing so will cause endless
* "spurious" i8259 interrupts to be fielded.
*/
// IDSEL 11 - iPMC712 PCI/ISA Bridge
0x5800 0x0 0x0 0x1 &mpic 0x0 0x2
0x5800 0x0 0x0 0x2 &mpic 0x0 0x2
0x5800 0x0 0x0 0x3 &mpic 0x0 0x2
0x5800 0x0 0x0 0x4 &mpic 0x0 0x2
/* IDSEL 12 - Not Used */
/* IDSEL 13 - Universe VME Bridge */
0x6800 0x0 0x0 0x1 &mpic 0x5 0x1
0x6800 0x0 0x0 0x2 &mpic 0x6 0x1
0x6800 0x0 0x0 0x3 &mpic 0x7 0x1
0x6800 0x0 0x0 0x4 &mpic 0x8 0x1
/* IDSEL 14 - ENET 1 */
0x7000 0x0 0x0 0x1 &mpic 0x2 0x1
/* IDSEL 15 - Not Used */
/* IDSEL 16 - PMC Slot 1 */
0x8000 0x0 0x0 0x1 &mpic 0x9 0x1
0x8000 0x0 0x0 0x2 &mpic 0xa 0x1
0x8000 0x0 0x0 0x3 &mpic 0xb 0x1
0x8000 0x0 0x0 0x4 &mpic 0xc 0x1
/* IDSEL 17 - PMC Slot 2 */
0x8800 0x0 0x0 0x1 &mpic 0xc 0x1
0x8800 0x0 0x0 0x2 &mpic 0x9 0x1
0x8800 0x0 0x0 0x3 &mpic 0xa 0x1
0x8800 0x0 0x0 0x4 &mpic 0xb 0x1
/* IDSEL 18 - Not Used */
/* IDSEL 19 - ENET 2 */
0x9800 0x0 0x0 0x1 &mpic 0xd 0x1
/* IDSEL 20 - PMCSPAN (PCI-X) */
0xa000 0x0 0x0 0x1 &mpic 0x9 0x1
0xa000 0x0 0x0 0x2 &mpic 0xa 0x1
0xa000 0x0 0x0 0x3 &mpic 0xb 0x1
0xa000 0x0 0x0 0x4 &mpic 0xc 0x1
>;
isa {
#address-cells = <2>;
#size-cells = <1>;
#interrupt-cells = <2>;
device_type = "isa";
compatible = "isa";
ranges = <0x00000001 0 0x01000000 0 0x00000000 0x00001000>;
interrupt-parent = <&i8259>;
i8259: interrupt-controller@20 {
#interrupt-cells = <2>;
#address-cells = <0>;
interrupts = <0 2>;
device_type = "interrupt-controller";
compatible = "chrp,iic";
interrupt-controller;
reg = <1 0x00000020 0x00000002
1 0x000000a0 0x00000002
1 0x000004d0 0x00000002>;
interrupt-parent = <&mpic>;
};
};
};
chosen {
linux,stdout-path = &serial0;
};
};
......@@ -15,52 +15,9 @@
model = "fsl,P1010RDB";
compatible = "fsl,P1010RDB";
memory {
device_type = "memory";
};
board_ifc: ifc: ifc@ffe1e000 {
/* NOR, NAND Flashes and CPLD on board */
ranges = <0x0 0x0 0x0 0xee000000 0x02000000
0x1 0x0 0x0 0xff800000 0x00010000
0x3 0x0 0x0 0xffb00000 0x00000020>;
reg = <0x0 0xffe1e000 0 0x2000>;
};
board_soc: soc: soc@ffe00000 {
ranges = <0x0 0x0 0xffe00000 0x100000>;
};
pci0: pcie@ffe09000 {
reg = <0 0xffe09000 0 0x1000>;
ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
pcie@0 {
ranges = <0x2000000 0x0 0xa0000000
0x2000000 0x0 0xa0000000
0x0 0x20000000
0x1000000 0x0 0x0
0x1000000 0x0 0x0
0x0 0x100000>;
};
};
pci1: pcie@ffe0a000 {
reg = <0 0xffe0a000 0 0x1000>;
ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
pcie@0 {
ranges = <0x2000000 0x0 0x80000000
0x2000000 0x0 0x80000000
0x0 0x20000000
0x1000000 0x0 0x0
0x1000000 0x0 0x0
0x0 0x100000>;
};
};
/include/ "p1010rdb_32b.dtsi"
};
/include/ "p1010rdb.dtsi"
/include/ "p1010rdb-pa.dtsi"
/include/ "fsl/p1010si-post.dtsi"
/*
* P1010 RDB Device Tree Source stub (no addresses or top-level ranges)
*
* Copyright 2013 Freescale Semiconductor Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions 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.
* * Neither the name of Freescale Semiconductor nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") as published by the Free Software
* Foundation, either version 2 of that License or (at your option) any
* later version.
*
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
*/
&ifc_nand {
partition@0 {
/* This location must not be altered */
/* 1MB for u-boot Bootloader Image */
reg = <0x0 0x00100000>;
label = "NAND U-Boot Image";
read-only;
};
partition@100000 {
/* 1MB for DTB Image */
reg = <0x00100000 0x00100000>;
label = "NAND DTB Image";
};
partition@200000 {
/* 4MB for Linux Kernel Image */
reg = <0x00200000 0x00400000>;
label = "NAND Linux Kernel Image";
};
partition@600000 {
/* 4MB for Compressed Root file System Image */
reg = <0x00600000 0x00400000>;
label = "NAND Compressed RFS Image";
};
partition@a00000 {
/* 15MB for JFFS2 based Root file System */
reg = <0x00a00000 0x00f00000>;
label = "NAND JFFS2 Root File System";
};
partition@1900000 {
/* 7MB for User Area */
reg = <0x01900000 0x00700000>;
label = "NAND User area";
};
};
&phy0 {
interrupts = <1 1 0 0>;
};
&phy1 {
interrupts = <2 1 0 0>;
};
&phy2 {
interrupts = <4 1 0 0>;
};
......@@ -38,52 +38,9 @@
model = "fsl,P1010RDB";
compatible = "fsl,P1010RDB";
memory {
device_type = "memory";
};
board_ifc: ifc: ifc@fffe1e000 {
/* NOR, NAND Flashes and CPLD on board */
ranges = <0x0 0x0 0xf 0xee000000 0x02000000
0x1 0x0 0xf 0xff800000 0x00010000
0x3 0x0 0xf 0xffb00000 0x00000020>;
reg = <0xf 0xffe1e000 0 0x2000>;
};
board_soc: soc: soc@fffe00000 {
ranges = <0x0 0xf 0xffe00000 0x100000>;
};
pci0: pcie@fffe09000 {
reg = <0xf 0xffe09000 0 0x1000>;
ranges = <0x2000000 0x0 0xc0000000 0xc 0x20000000 0x0 0x20000000
0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
pcie@0 {
ranges = <0x2000000 0x0 0xc0000000
0x2000000 0x0 0xc0000000
0x0 0x20000000
0x1000000 0x0 0x0
0x1000000 0x0 0x0
0x0 0x100000>;
};
};
pci1: pcie@fffe0a000 {
reg = <0xf 0xffe0a000 0 0x1000>;
ranges = <0x2000000 0x0 0xc0000000 0xc 0x20000000 0x0 0x20000000
0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
pcie@0 {
ranges = <0x2000000 0x0 0xc0000000
0x2000000 0x0 0xc0000000
0x0 0x20000000
0x1000000 0x0 0x0
0x1000000 0x0 0x0
0x0 0x100000>;
};
};
/include/ "p1010rdb_36b.dtsi"
};
/include/ "p1010rdb.dtsi"
/include/ "p1010rdb-pa.dtsi"
/include/ "fsl/p1010si-post.dtsi"
/*
* P1010 RDB Device Tree Source
*
* Copyright 2011 Freescale Semiconductor Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
/include/ "fsl/p1010si-pre.dtsi"
/ {
model = "fsl,P1010RDB-PB";
compatible = "fsl,P1010RDB-PB";
/include/ "p1010rdb_32b.dtsi"
};
/include/ "p1010rdb.dtsi"
&phy0 {
interrupts = <0 1 0 0>;
};
&phy1 {
interrupts = <2 1 0 0>;
};
&phy2 {
interrupts = <1 1 0 0>;
};
/include/ "fsl/p1010si-post.dtsi"
/*
* P1010 RDB Device Tree Source (36-bit address map)
*
* Copyright 2011 Freescale Semiconductor Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions 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.
* * Neither the name of Freescale Semiconductor nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") as published by the Free Software
* Foundation, either version 2 of that License or (at your option) any
* later version.
*
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
*/
/include/ "fsl/p1010si-pre.dtsi"
/ {
model = "fsl,P1010RDB-PB";
compatible = "fsl,P1010RDB-PB";
/include/ "p1010rdb_36b.dtsi"
};
/include/ "p1010rdb.dtsi"
&phy0 {
interrupts = <0 1 0 0>;
};
&phy1 {
interrupts = <2 1 0 0>;
};
&phy2 {
interrupts = <1 1 0 0>;
};
/include/ "fsl/p1010si-post.dtsi"
......@@ -69,49 +69,11 @@
};
};
nand@1,0 {
ifc_nand: nand@1,0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "fsl,ifc-nand";
reg = <0x1 0x0 0x10000>;
partition@0 {
/* This location must not be altered */
/* 1MB for u-boot Bootloader Image */
reg = <0x0 0x00100000>;
label = "NAND U-Boot Image";
read-only;
};
partition@100000 {
/* 1MB for DTB Image */
reg = <0x00100000 0x00100000>;
label = "NAND DTB Image";
};
partition@200000 {
/* 4MB for Linux Kernel Image */
reg = <0x00200000 0x00400000>;
label = "NAND Linux Kernel Image";
};
partition@600000 {
/* 4MB for Compressed Root file System Image */
reg = <0x00600000 0x00400000>;
label = "NAND Compressed RFS Image";
};
partition@a00000 {
/* 15MB for JFFS2 based Root file System */
reg = <0x00a00000 0x00f00000>;
label = "NAND JFFS2 Root File System";
};
partition@1900000 {
/* 7MB for User Area */
reg = <0x01900000 0x00700000>;
label = "NAND User area";
};
};
cpld@3,0 {
......@@ -193,17 +155,14 @@
mdio@24000 {
phy0: ethernet-phy@0 {
interrupts = <3 1 0 0>;
reg = <0x1>;
};
phy1: ethernet-phy@1 {
interrupts = <2 1 0 0>;
reg = <0x0>;
};
phy2: ethernet-phy@2 {
interrupts = <2 1 0 0>;
reg = <0x2>;
};
......
/*
* P1010 RDB Device Tree Source stub (no addresses or top-level ranges)
*
* Copyright 2013 Freescale Semiconductor Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions 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.
* * Neither the name of Freescale Semiconductor nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") as published by the Free Software
* Foundation, either version 2 of that License or (at your option) any
* later version.
*
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
*/
memory {
device_type = "memory";
};
board_ifc: ifc: ifc@ffe1e000 {
/* NOR, NAND Flashes and CPLD on board */
ranges = <0x0 0x0 0x0 0xee000000 0x02000000
0x1 0x0 0x0 0xff800000 0x00010000
0x3 0x0 0x0 0xffb00000 0x00000020>;
reg = <0x0 0xffe1e000 0 0x2000>;
};
board_soc: soc: soc@ffe00000 {
ranges = <0x0 0x0 0xffe00000 0x100000>;
};
pci0: pcie@ffe09000 {
reg = <0 0xffe09000 0 0x1000>;
ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
pcie@0 {
ranges = <0x2000000 0x0 0xa0000000
0x2000000 0x0 0xa0000000
0x0 0x20000000
0x1000000 0x0 0x0
0x1000000 0x0 0x0
0x0 0x100000>;
};
};
pci1: pcie@ffe0a000 {
reg = <0 0xffe0a000 0 0x1000>;
ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
pcie@0 {
ranges = <0x2000000 0x0 0x80000000
0x2000000 0x0 0x80000000
0x0 0x20000000
0x1000000 0x0 0x0
0x1000000 0x0 0x0
0x0 0x100000>;
};
};
/*
* P1010 RDB Device Tree Source stub (no addresses or top-level ranges)
*
* Copyright 2013 Freescale Semiconductor Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions 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.
* * Neither the name of Freescale Semiconductor nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") as published by the Free Software
* Foundation, either version 2 of that License or (at your option) any
* later version.
*
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
*/
memory {
device_type = "memory";
};
board_ifc: ifc: ifc@fffe1e000 {
/* NOR, NAND Flashes and CPLD on board */
ranges = <0x0 0x0 0xf 0xee000000 0x02000000
0x1 0x0 0xf 0xff800000 0x00010000
0x3 0x0 0xf 0xffb00000 0x00000020>;
reg = <0xf 0xffe1e000 0 0x2000>;
};
board_soc: soc: soc@fffe00000 {
ranges = <0x0 0xf 0xffe00000 0x100000>;
};
pci0: pcie@fffe09000 {
reg = <0xf 0xffe09000 0 0x1000>;
ranges = <0x2000000 0x0 0xc0000000 0xc 0x20000000 0x0 0x20000000
0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
pcie@0 {
ranges = <0x2000000 0x0 0xc0000000
0x2000000 0x0 0xc0000000
0x0 0x20000000
0x1000000 0x0 0x0
0x1000000 0x0 0x0
0x0 0x100000>;
};
};
pci1: pcie@fffe0a000 {
reg = <0xf 0xffe0a000 0 0x1000>;
ranges = <0x2000000 0x0 0xc0000000 0xc 0x20000000 0x0 0x20000000
0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
pcie@0 {
ranges = <0x2000000 0x0 0xc0000000
0x2000000 0x0 0xc0000000
0x0 0x20000000
0x1000000 0x0 0x0
0x1000000 0x0 0x0
0x0 0x100000>;
};
};
......@@ -146,8 +146,9 @@
*/
};
rtc@68 {
compatible = "dallas,ds1339";
compatible = "dallas,ds3232";
reg = <0x68>;
interrupts = <0x1 0x1 0 0>;
};
adt7461@4c {
compatible = "adi,adt7461";
......
/*
* P1025 TWR Device Tree Source (32-bit address map)
*
* Copyright 2013 Freescale Semiconductor Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions 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.
* * Neither the name of Freescale Semiconductor nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") as published by the Free Software
* Foundation, either version 2 of that License or (at your option) any
* later version.
*
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
*/
/include/ "fsl/p1021si-pre.dtsi"
/ {
model = "fsl,P1025";
compatible = "fsl,TWR-P1025";
memory {
device_type = "memory";
};
lbc: localbus@ffe05000 {
reg = <0 0xffe05000 0 0x1000>;
/* NOR Flash and SSD1289 */
ranges = <0x0 0x0 0x0 0xec000000 0x04000000
0x2 0x0 0x0 0xe0000000 0x00020000>;
};
soc: soc@ffe00000 {
ranges = <0x0 0x0 0xffe00000 0x100000>;
};
pci0: pcie@ffe09000 {
ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
reg = <0 0xffe09000 0 0x1000>;
pcie@0 {
ranges = <0x2000000 0x0 0xa0000000
0x2000000 0x0 0xa0000000
0x0 0x20000000
0x1000000 0x0 0x0
0x1000000 0x0 0x0
0x0 0x100000>;
};
};
pci1: pcie@ffe0a000 {
reg = <0 0xffe0a000 0 0x1000>;
ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
pcie@0 {
ranges = <0x2000000 0x0 0x80000000
0x2000000 0x0 0x80000000
0x0 0x20000000
0x1000000 0x0 0x0
0x1000000 0x0 0x0
0x0 0x100000>;
};
};
qe: qe@ffe80000 {
ranges = <0x0 0x0 0xffe80000 0x40000>;
reg = <0 0xffe80000 0 0x480>;
brg-frequency = <0>;
bus-frequency = <0>;
};
};
/include/ "p1025twr.dtsi"
/include/ "fsl/p1021si-post.dtsi"
/*
* P1025 TWR Device Tree Source stub (no addresses or top-level ranges)
*
* Copyright 2013 Freescale Semiconductor Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions 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.
* * Neither the name of Freescale Semiconductor nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") as published by the Free Software
* Foundation, either version 2 of that License or (at your option) any
* later version.
*
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
*/
/{
aliases {
ethernet3 = &enet3;
ethernet4 = &enet4;
};
};
&lbc {
nor@0,0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cfi-flash";
reg = <0x0 0x0 0x4000000>;
bank-width = <2>;
device-width = <1>;
partition@0 {
/* This location must not be altered */
/* 256KB for Vitesse 7385 Switch firmware */
reg = <0x0 0x00040000>;
label = "NOR Vitesse-7385 Firmware";
read-only;
};
partition@40000 {
/* 256KB for DTB Image */
reg = <0x00040000 0x00040000>;
label = "NOR DTB Image";
};
partition@80000 {
/* 5.5 MB for Linux Kernel Image */
reg = <0x00080000 0x00580000>;
label = "NOR Linux Kernel Image";
};
partition@400000 {
/* 56.75MB for Root file System */
reg = <0x00600000 0x038c0000>;
label = "NOR Root File System";
};
partition@ec0000 {
/* This location must not be altered */
/* 256KB for QE ucode firmware*/
reg = <0x03ec0000 0x00040000>;
label = "NOR QE microcode firmware";
read-only;
};
partition@f00000 {
/* This location must not be altered */
/* 512KB for u-boot Bootloader Image */
/* 512KB for u-boot Environment Variables */
reg = <0x03f00000 0x00100000>;
label = "NOR U-Boot Image";
read-only;
};
};
/* CS2 for Display */
display@2,0 {
compatible = "solomon,ssd1289fb";
reg = <0x2 0x0000 0x0004>;
};
};
&soc {
usb@22000 {
phy_type = "ulpi";
};
mdio@24000 {
phy0: ethernet-phy@2 {
interrupt-parent = <&mpic>;
interrupts = <1 1 0 0>;
reg = <0x2>;
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
interrupts = <2 1 0 0>;
reg = <0x1>;
};
tbi0: tbi-phy@11 {
reg = <0x11>;
device_type = "tbi-phy";
};
};
mdio@25000 {
tbi1: tbi-phy@11 {
reg = <0x11>;
device_type = "tbi-phy";
};
};
mdio@26000 {
tbi2: tbi-phy@11 {
reg = <0x11>;
device_type = "tbi-phy";
};
};
enet0: ethernet@b0000 {
phy-handle = <&phy0>;
phy-connection-type = "rgmii-id";
};
enet1: ethernet@b1000 {
status = "disabled";
};
enet2: ethernet@b2000 {
phy-handle = <&phy1>;
phy-connection-type = "rgmii-id";
};
par_io@e0100 {
#address-cells = <1>;
#size-cells = <1>;
reg = <0xe0100 0x60>;
ranges = <0x0 0xe0100 0x60>;
device_type = "par_io";
num-ports = <3>;
pio1: ucc_pin@01 {
pio-map = <
/* port pin dir open_drain assignment has_irq */
0x1 0x13 0x1 0x0 0x1 0x0 /* QE_MUX_MDC */
0x1 0x14 0x3 0x0 0x1 0x0 /* QE_MUX_MDIO */
0x0 0x17 0x2 0x0 0x2 0x0 /* CLK12 */
0x0 0x18 0x2 0x0 0x1 0x0 /* CLK9 */
0x0 0x7 0x1 0x0 0x2 0x0 /* ENET1_TXD0_SER1_TXD0 */
0x0 0x9 0x1 0x0 0x2 0x0 /* ENET1_TXD1_SER1_TXD1 */
0x0 0xb 0x1 0x0 0x2 0x0 /* ENET1_TXD2_SER1_TXD2 */
0x0 0xc 0x1 0x0 0x2 0x0 /* ENET1_TXD3_SER1_TXD3 */
0x0 0x6 0x2 0x0 0x2 0x0 /* ENET1_RXD0_SER1_RXD0 */
0x0 0xa 0x2 0x0 0x2 0x0 /* ENET1_RXD1_SER1_RXD1 */
0x0 0xe 0x2 0x0 0x2 0x0 /* ENET1_RXD2_SER1_RXD2 */
0x0 0xf 0x2 0x0 0x2 0x0 /* ENET1_RXD3_SER1_RXD3 */
0x0 0x5 0x1 0x0 0x2 0x0 /* ENET1_TX_EN_SER1_RTS_B */
0x0 0xd 0x1 0x0 0x2 0x0 /* ENET1_TX_ER */
0x0 0x4 0x2 0x0 0x2 0x0 /* ENET1_RX_DV_SER1_CTS_B */
0x0 0x8 0x2 0x0 0x2 0x0 /* ENET1_RX_ER_SER1_CD_B */
0x0 0x11 0x2 0x0 0x2 0x0 /* ENET1_CRS */
0x0 0x10 0x2 0x0 0x2 0x0>; /* ENET1_COL */
};
pio2: ucc_pin@02 {
pio-map = <
/* port pin dir open_drain assignment has_irq */
0x1 0x13 0x1 0x0 0x1 0x0 /* QE_MUX_MDC */
0x1 0x14 0x3 0x0 0x1 0x0 /* QE_MUX_MDIO */
0x1 0xb 0x2 0x0 0x1 0x0 /* CLK13 */
0x1 0x7 0x1 0x0 0x2 0x0 /* ENET5_TXD0_SER5_TXD0 */
0x1 0xa 0x1 0x0 0x2 0x0 /* ENET5_TXD1_SER5_TXD1 */
0x1 0x6 0x2 0x0 0x2 0x0 /* ENET5_RXD0_SER5_RXD0 */
0x1 0x9 0x2 0x0 0x2 0x0 /* ENET5_RXD1_SER5_RXD1 */
0x1 0x5 0x1 0x0 0x2 0x0 /* ENET5_TX_EN_SER5_RTS_B */
0x1 0x4 0x2 0x0 0x2 0x0 /* ENET5_RX_DV_SER5_CTS_B */
0x1 0x8 0x2 0x0 0x2 0x0>; /* ENET5_RX_ER_SER5_CD_B */
};
pio3: ucc_pin@03 {
pio-map = <
/* port pin dir open_drain assignment has_irq */
0x0 0x16 0x2 0x0 0x2 0x0 /* SER7_CD_B*/
0x0 0x12 0x2 0x0 0x2 0x0 /* SER7_CTS_B*/
0x0 0x13 0x1 0x0 0x2 0x0 /* SER7_RTS_B*/
0x0 0x14 0x2 0x0 0x2 0x0 /* SER7_RXD0*/
0x0 0x15 0x1 0x0 0x2 0x0>; /* SER7_TXD0*/
};
pio4: ucc_pin@04 {
pio-map = <
/* port pin dir open_drain assignment has_irq */
0x1 0x0 0x2 0x0 0x2 0x0 /* SER3_CD_B*/
0x0 0x1c 0x2 0x0 0x2 0x0 /* SER3_CTS_B*/
0x0 0x1d 0x1 0x0 0x2 0x0 /* SER3_RTS_B*/
0x0 0x1e 0x2 0x0 0x2 0x0 /* SER3_RXD0*/
0x0 0x1f 0x1 0x0 0x2 0x0>; /* SER3_TXD0*/
};
};
};
&qe {
enet3: ucc@2000 {
device_type = "network";
compatible = "ucc_geth";
rx-clock-name = "clk12";
tx-clock-name = "clk9";
pio-handle = <&pio1>;
phy-handle = <&qe_phy0>;
phy-connection-type = "mii";
};
mdio@2120 {
qe_phy0: ethernet-phy@18 {
interrupt-parent = <&mpic>;
interrupts = <4 1 0 0>;
reg = <0x18>;
device_type = "ethernet-phy";
};
qe_phy1: ethernet-phy@19 {
interrupt-parent = <&mpic>;
interrupts = <5 1 0 0>;
reg = <0x19>;
device_type = "ethernet-phy";
};
tbi-phy@11 {
reg = <0x11>;
device_type = "tbi-phy";
};
};
enet4: ucc@2400 {
device_type = "network";
compatible = "ucc_geth";
rx-clock-name = "none";
tx-clock-name = "clk13";
pio-handle = <&pio2>;
phy-handle = <&qe_phy1>;
phy-connection-type = "rmii";
};
serial2: ucc@2600 {
device_type = "serial";
compatible = "ucc_uart";
port-number = <0>;
rx-clock-name = "brg6";
tx-clock-name = "brg6";
pio-handle = <&pio3>;
};
serial3: ucc@2200 {
device_type = "serial";
compatible = "ucc_uart";
port-number = <1>;
rx-clock-name = "brg2";
tx-clock-name = "brg2";
pio-handle = <&pio4>;
};
};
......@@ -257,6 +257,8 @@
#size-cells = <1>;
compatible = "xlnx,compound";
ethernet@81c00000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "xlnx,xps-ll-temac-1.01.b";
device_type = "network";
interrupt-parent = <&xps_intc_0>;
......
/*
* Motorola/Emerson MVME5100 with PPCBug firmware.
*
* Author: Stephen Chivers <schivers@csc.com>
*
* Copyright 2013 CSC Australia Pty. Ltd.
*
* 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 "types.h"
#include "ops.h"
#include "io.h"
BSS_STACK(4096);
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5)
{
u32 heapsize;
heapsize = 0x8000000 - (u32)_end; /* 128M */
simple_alloc_init(_end, heapsize, 32, 64);
fdt_init(_dtb_start);
serial_console_init();
}
......@@ -265,6 +265,10 @@ epapr)
link_address='0x20000000'
pie=-pie
;;
mvme5100)
platformo="$object/fixed-head.o $object/mvme5100.o"
binary=y
;;
esac
vmz="$tmpdir/`basename \"$kernel\"`.$ext"
......
CONFIG_PPC_85xx=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_AUDIT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_RCU_FANOUT=32
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_PARTITION_ADVANCED=y
CONFIG_MAC_PARTITION=y
CONFIG_PHYSICAL_START=0x00000000
CONFIG_P1023_RDB=y
CONFIG_P1023_RDS=y
CONFIG_QUICC_ENGINE=y
CONFIG_QE_GPIO=y
CONFIG_CPM2=y
CONFIG_HIGHMEM=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_BINFMT_MISC=m
CONFIG_MATH_EMULATION=y
CONFIG_SWIOTLB=y
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
# CONFIG_PCIEAER is not set
# CONFIG_PCIEASPM is not set
CONFIG_PCI_MSI=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
CONFIG_NET_KEY=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_MULTIPATH=y
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
CONFIG_NET_IPIP=y
CONFIG_IP_MROUTE=y
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
CONFIG_ARPD=y
CONFIG_INET_ESP=y
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
CONFIG_IPV6=y
CONFIG_IP_SCTP=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_PHYSMAP_OF=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_FSL_ELBC=y
CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=131072
CONFIG_EEPROM_AT24=y
CONFIG_EEPROM_LEGACY=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=y
CONFIG_BLK_DEV_SR=y
CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_LOGGING=y
CONFIG_ATA=y
CONFIG_SATA_FSL=y
CONFIG_SATA_SIL24=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_FS_ENET=y
CONFIG_FSL_PQ_MDIO=y
CONFIG_E1000E=y
CONFIG_PHYLIB=y
CONFIG_AT803X_PHY=y
CONFIG_MARVELL_PHY=y
CONFIG_DAVICOM_PHY=y
CONFIG_CICADA_PHY=y
CONFIG_VITESSE_PHY=y
CONFIG_FIXED_PHY=y
CONFIG_INPUT_FF_MEMLESS=m
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_SERIO_LIBPS2=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=2
CONFIG_SERIAL_8250_RUNTIME_UARTS=2
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_DETECT_IRQ=y
CONFIG_SERIAL_8250_RSA=y
CONFIG_HW_RANDOM=y
CONFIG_NVRAM=y
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_CPM=m
CONFIG_I2C_MPC=y
CONFIG_GPIO_MPC8XXX=y
# CONFIG_HWMON is not set
CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
# CONFIG_SND_SUPPORT_OLD_API is not set
CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_FSL=y
CONFIG_USB_STORAGE=y
CONFIG_EDAC=y
CONFIG_EDAC_MM_EDAC=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_DS1307=y
CONFIG_RTC_DRV_CMOS=y
CONFIG_DMADEVICES=y
CONFIG_FSL_DMA=y
# CONFIG_NET_DMA is not set
CONFIG_STAGING=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_ISO9660_FS=m
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
CONFIG_UDF_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=y
CONFIG_NTFS_FS=y
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_ADFS_FS=m
CONFIG_AFFS_FS=m
CONFIG_HFS_FS=m
CONFIG_HFSPLUS_FS=m
CONFIG_BEFS_FS=m
CONFIG_BFS_FS=m
CONFIG_EFS_FS=m
CONFIG_CRAMFS=y
CONFIG_VXFS_FS=m
CONFIG_HPFS_FS=m
CONFIG_QNX4FS_FS=m
CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
CONFIG_NFS_FS=y
CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
CONFIG_NFSD=y
CONFIG_CRC_T10DIF=y
CONFIG_FRAME_WARN=8092
CONFIG_DEBUG_FS=y
CONFIG_DETECT_HUNG_TASK=y
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DEBUG_INFO=y
CONFIG_STRICT_DEVMEM=y
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_AES=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_DEV_FSL_CAAM=y
......@@ -70,3 +70,4 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_INFO=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_CRC32_SLICEBY4=y
......@@ -72,3 +72,4 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_INFO=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_CRC32_SLICEBY4=y
......@@ -31,6 +31,7 @@ CONFIG_C293_PCIE=y
CONFIG_P1010_RDB=y
CONFIG_P1022_DS=y
CONFIG_P1022_RDK=y
CONFIG_P1023_RDB=y
CONFIG_P1023_RDS=y
CONFIG_SOCRATES=y
CONFIG_KSI8560=y
......@@ -113,6 +114,7 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=131072
CONFIG_EEPROM_AT24=y
CONFIG_EEPROM_LEGACY=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=y
......@@ -211,6 +213,7 @@ CONFIG_EDAC=y
CONFIG_EDAC_MM_EDAC=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_CMOS=y
CONFIG_RTC_DRV_DS1307=y
CONFIG_DMADEVICES=y
CONFIG_FSL_DMA=y
# CONFIG_NET_DMA is not set
......
......@@ -34,6 +34,7 @@ CONFIG_C293_PCIE=y
CONFIG_P1010_RDB=y
CONFIG_P1022_DS=y
CONFIG_P1022_RDK=y
CONFIG_P1023_RDB=y
CONFIG_P1023_RDS=y
CONFIG_SOCRATES=y
CONFIG_KSI8560=y
......@@ -116,6 +117,7 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=131072
CONFIG_EEPROM_AT24=y
CONFIG_EEPROM_LEGACY=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=y
......@@ -212,6 +214,7 @@ CONFIG_EDAC=y
CONFIG_EDAC_MM_EDAC=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_CMOS=y
CONFIG_RTC_DRV_DS1307=y
CONFIG_DMADEVICES=y
CONFIG_FSL_DMA=y
# CONFIG_NET_DMA is not set
......
......@@ -55,3 +55,4 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_CRC_CCITT=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRC32_SLICEBY4=y
......@@ -78,3 +78,4 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_INFO=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_CRC32_SLICEBY4=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_UTS_NS is not set
# CONFIG_IPC_NS is not set
# CONFIG_PID_NS is not set
# CONFIG_NET_NS is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_COMPAT_BRK is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_PPC_CHRP is not set
# CONFIG_PPC_PMAC is not set
CONFIG_EMBEDDED6xx=y
CONFIG_MVME5100=y
CONFIG_KVM_GUEST=y
CONFIG_HZ_100=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_COMPACTION is not set
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyS0,9600 ip=dhcp root=/dev/nfs"
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_LRO is not set
# CONFIG_IPV6 is not set
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=m
CONFIG_NF_CT_PROTO_SCTP=m
CONFIG_NF_CONNTRACK_AMANDA=m
CONFIG_NF_CONNTRACK_FTP=m
CONFIG_NF_CONNTRACK_H323=m
CONFIG_NF_CONNTRACK_IRC=m
CONFIG_NF_CONNTRACK_NETBIOS_NS=m
CONFIG_NF_CONNTRACK_PPTP=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_LAPB=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=2
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_EEPROM_LEGACY=m
CONFIG_NETDEVICES=y
CONFIG_TUN=m
# CONFIG_NET_VENDOR_3COM is not set
CONFIG_E100=y
# CONFIG_WLAN is not set
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO is not set
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=10
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_HW_RANDOM=y
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MPC=y
# CONFIG_HWMON is not set
CONFIG_VIDEO_OUTPUT_CONTROL=m
# CONFIG_VGA_CONSOLE is not set
# CONFIG_HID is not set
# CONFIG_USB_SUPPORT is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_VME_BUS=m
CONFIG_VME_CA91CX42=m
CONFIG_EXT2_FS=m
CONFIG_EXT3_FS=m
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_XFS_FS=m
CONFIG_ISO9660_FS=m
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
CONFIG_UDF_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
CONFIG_NFSD=m
CONFIG_NFSD_V3=y
CONFIG_CIFS=m
CONFIG_NLS=y
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_CODEPAGE_932=m
CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_UTF8=m
CONFIG_CRC_CCITT=m
CONFIG_CRC_T10DIF=y
CONFIG_XZ_DEC=y
CONFIG_XZ_DEC_X86=y
CONFIG_XZ_DEC_IA64=y
CONFIG_XZ_DEC_ARM=y
CONFIG_XZ_DEC_ARMTHUMB=y
CONFIG_XZ_DEC_SPARC=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=20
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_DEFLATE=m
# CONFIG_CRYPTO_ANSI_CPRNG is not set
......@@ -186,6 +186,7 @@ CONFIG_SCSI_DH_RDAC=m
CONFIG_SCSI_DH_ALUA=m
CONFIG_ATA=y
CONFIG_SATA_SIL24=y
CONFIG_SATA_MV=y
CONFIG_SATA_SVW=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
......
......@@ -84,3 +84,4 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_INFO=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_CRC32_SLICEBY4=y
......@@ -46,6 +46,11 @@
#include <asm/asm-compat.h>
#include <asm/synch.h>
/* PPC bit number conversion */
#define PPC_BITLSHIFT(be) (BITS_PER_LONG - 1 - (be))
#define PPC_BIT(bit) (1UL << PPC_BITLSHIFT(bit))
#define PPC_BITMASK(bs, be) ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
/*
* clear_bit doesn't imply a memory barrier
*/
......
......@@ -41,8 +41,20 @@ struct ppc64_caches {
extern struct ppc64_caches ppc64_caches;
#endif /* __powerpc64__ && ! __ASSEMBLY__ */
#if !defined(__ASSEMBLY__)
#if defined(__ASSEMBLY__)
/*
* For a snooping icache, we still need a dummy icbi to purge all the
* prefetched instructions from the ifetch buffers. We also need a sync
* before the icbi to order the the actual stores to memory that might
* have modified instructions with the icbi.
*/
#define PURGE_PREFETCHED_INS \
sync; \
icbi 0,r3; \
sync; \
isync
#else
#define __read_mostly __attribute__((__section__(".data..read_mostly")))
#ifdef CONFIG_6xx
......
......@@ -300,6 +300,7 @@ __cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
cmpxchg_local((ptr), (o), (n)); \
})
#define cmpxchg64_relaxed cmpxchg64_local
#else
#include <asm-generic/cmpxchg-local.h>
#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
......
......@@ -34,6 +34,13 @@ int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr);
unsigned long branch_target(const unsigned int *instr);
unsigned int translate_branch(const unsigned int *dest,
const unsigned int *src);
#ifdef CONFIG_PPC_BOOK3E_64
void __patch_exception(int exc, unsigned long addr);
#define patch_exception(exc, name) do { \
extern unsigned int name; \
__patch_exception((exc), (unsigned long)&name); \
} while (0)
#endif
static inline unsigned long ppc_function_entry(void *func)
{
......
......@@ -90,6 +90,18 @@ struct cpu_spec {
* if the error is fatal, 1 if it was fully recovered and 0 to
* pass up (not CPU originated) */
int (*machine_check)(struct pt_regs *regs);
/*
* Processor specific early machine check handler which is
* called in real mode to handle SLB and TLB errors.
*/
long (*machine_check_early)(struct pt_regs *regs);
/*
* Processor specific routine to flush tlbs.
*/
void (*flush_tlb)(unsigned long inval_selector);
};
extern struct cpu_spec *cur_cpu_spec;
......
......@@ -90,7 +90,8 @@ struct eeh_pe {
#define EEH_DEV_IRQ_DISABLED (1 << 3) /* Interrupt disabled */
#define EEH_DEV_DISCONNECTED (1 << 4) /* Removing from PE */
#define EEH_DEV_SYSFS (1 << 8) /* Sysfs created */
#define EEH_DEV_NO_HANDLER (1 << 8) /* No error handler */
#define EEH_DEV_SYSFS (1 << 9) /* Sysfs created */
struct eeh_dev {
int mode; /* EEH mode */
......@@ -117,6 +118,16 @@ static inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev)
return edev ? edev->pdev : NULL;
}
/* Return values from eeh_ops::next_error */
enum {
EEH_NEXT_ERR_NONE = 0,
EEH_NEXT_ERR_INF,
EEH_NEXT_ERR_FROZEN_PE,
EEH_NEXT_ERR_FENCED_PHB,
EEH_NEXT_ERR_DEAD_PHB,
EEH_NEXT_ERR_DEAD_IOC
};
/*
* The struct is used to trace the registered EEH operation
* callback functions. Actually, those operation callback
......@@ -157,6 +168,7 @@ struct eeh_ops {
int (*read_config)(struct device_node *dn, int where, int size, u32 *val);
int (*write_config)(struct device_node *dn, int where, int size, u32 val);
int (*next_error)(struct eeh_pe **pe);
int (*restore_config)(struct device_node *dn);
};
extern struct eeh_ops *eeh_ops;
......
......@@ -301,9 +301,12 @@ do_kvm_##n: \
beq 4f; /* if from kernel mode */ \
ACCOUNT_CPU_USER_ENTRY(r9, r10); \
SAVE_PPR(area, r9, r10); \
4: std r2,GPR2(r1); /* save r2 in stackframe */ \
SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \
SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \
4: EXCEPTION_PROLOG_COMMON_2(area) \
EXCEPTION_PROLOG_COMMON_3(n) \
ACCOUNT_STOLEN_TIME
/* Save original regs values from save area to stack frame. */
#define EXCEPTION_PROLOG_COMMON_2(area) \
ld r9,area+EX_R9(r13); /* move r9, r10 to stackframe */ \
ld r10,area+EX_R10(r13); \
std r9,GPR9(r1); \
......@@ -318,11 +321,16 @@ do_kvm_##n: \
ld r10,area+EX_CFAR(r13); \
std r10,ORIG_GPR3(r1); \
END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66); \
GET_CTR(r10, area); \
std r10,_CTR(r1);
#define EXCEPTION_PROLOG_COMMON_3(n) \
std r2,GPR2(r1); /* save r2 in stackframe */ \
SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \
SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \
mflr r9; /* Get LR, later save to stack */ \
ld r2,PACATOC(r13); /* get kernel TOC into r2 */ \
std r9,_LINK(r1); \
GET_CTR(r10, area); \
std r10,_CTR(r1); \
lbz r10,PACASOFTIRQEN(r13); \
mfspr r11,SPRN_XER; /* save XER in stackframe */ \
std r10,SOFTE(r1); \
......@@ -332,8 +340,7 @@ do_kvm_##n: \
li r10,0; \
ld r11,exception_marker@toc(r2); \
std r10,RESULT(r1); /* clear regs->result */ \
std r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */ \
ACCOUNT_STOLEN_TIME
std r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */
/*
* Exception vectors.
......
......@@ -285,7 +285,7 @@ struct fsl_lbc_ctrl {
/* device info */
struct device *dev;
struct fsl_lbc_regs __iomem *regs;
int irq;
int irq[2];
wait_queue_head_t irq_wait;
spinlock_t lock;
void *nand;
......
......@@ -6,7 +6,8 @@
typedef struct {
unsigned int __softirq_pending;
unsigned int timer_irqs;
unsigned int timer_irqs_event;
unsigned int timer_irqs_others;
unsigned int pmu_irqs;
unsigned int mce_exceptions;
unsigned int spurious_irqs;
......
......@@ -191,8 +191,24 @@ DEF_MMIO_OUT_D(out_le32, 32, stw);
#endif /* __BIG_ENDIAN */
/*
* Cache inhibitied accessors for use in real mode, you don't want to use these
* unless you know what you're doing.
*
* NB. These use the cpu byte ordering.
*/
DEF_MMIO_OUT_X(out_rm8, 8, stbcix);
DEF_MMIO_OUT_X(out_rm16, 16, sthcix);
DEF_MMIO_OUT_X(out_rm32, 32, stwcix);
DEF_MMIO_IN_X(in_rm8, 8, lbzcix);
DEF_MMIO_IN_X(in_rm16, 16, lhzcix);
DEF_MMIO_IN_X(in_rm32, 32, lwzcix);
#ifdef __powerpc64__
DEF_MMIO_OUT_X(out_rm64, 64, stdcix);
DEF_MMIO_IN_X(in_rm64, 64, ldcix);
#ifdef __BIG_ENDIAN__
DEF_MMIO_OUT_D(out_be64, 64, std);
DEF_MMIO_IN_D(in_be64, 64, ld);
......
......@@ -30,22 +30,19 @@
#include <asm/machdep.h>
#include <asm/types.h>
#define IOMMU_PAGE_SHIFT 12
#define IOMMU_PAGE_SIZE (ASM_CONST(1) << IOMMU_PAGE_SHIFT)
#define IOMMU_PAGE_MASK (~((1 << IOMMU_PAGE_SHIFT) - 1))
#define IOMMU_PAGE_ALIGN(addr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE)
#define IOMMU_PAGE_SHIFT_4K 12
#define IOMMU_PAGE_SIZE_4K (ASM_CONST(1) << IOMMU_PAGE_SHIFT_4K)
#define IOMMU_PAGE_MASK_4K (~((1 << IOMMU_PAGE_SHIFT_4K) - 1))
#define IOMMU_PAGE_ALIGN_4K(addr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE_4K)
#define IOMMU_PAGE_SIZE(tblptr) (ASM_CONST(1) << (tblptr)->it_page_shift)
#define IOMMU_PAGE_MASK(tblptr) (~((1 << (tblptr)->it_page_shift) - 1))
#define IOMMU_PAGE_ALIGN(addr, tblptr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE(tblptr))
/* Boot time flags */
extern int iommu_is_off;
extern int iommu_force_on;
/* Pure 2^n version of get_order */
static __inline__ __attribute_const__ int get_iommu_order(unsigned long size)
{
return __ilog2((size - 1) >> IOMMU_PAGE_SHIFT) + 1;
}
/*
* IOMAP_MAX_ORDER defines the largest contiguous block
* of dma space we can get. IOMAP_MAX_ORDER = 13
......@@ -76,11 +73,20 @@ struct iommu_table {
struct iommu_pool large_pool;
struct iommu_pool pools[IOMMU_NR_POOLS];
unsigned long *it_map; /* A simple allocation bitmap for now */
unsigned long it_page_shift;/* table iommu page size */
#ifdef CONFIG_IOMMU_API
struct iommu_group *it_group;
#endif
};
/* Pure 2^n version of get_order */
static inline __attribute_const__
int get_iommu_order(unsigned long size, struct iommu_table *tbl)
{
return __ilog2((size - 1) >> tbl->it_page_shift) + 1;
}
struct scatterlist;
static inline void set_iommu_table_base(struct device *dev, void *base)
......@@ -101,8 +107,34 @@ extern void iommu_free_table(struct iommu_table *tbl, const char *node_name);
*/
extern struct iommu_table *iommu_init_table(struct iommu_table * tbl,
int nid);
#ifdef CONFIG_IOMMU_API
extern void iommu_register_group(struct iommu_table *tbl,
int pci_domain_number, unsigned long pe_num);
extern int iommu_add_device(struct device *dev);
extern void iommu_del_device(struct device *dev);
#else
static inline void iommu_register_group(struct iommu_table *tbl,
int pci_domain_number,
unsigned long pe_num)
{
}
static inline int iommu_add_device(struct device *dev)
{
return 0;
}
static inline void iommu_del_device(struct device *dev)
{
}
#endif /* !CONFIG_IOMMU_API */
static inline void set_iommu_table_base_and_group(struct device *dev,
void *base)
{
set_iommu_table_base(dev, base);
iommu_add_device(dev);
}
extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
struct scatterlist *sglist, int nelems,
......
......@@ -74,6 +74,7 @@
#define BOOKE_INTERRUPT_GUEST_DBELL_CRIT 39
#define BOOKE_INTERRUPT_HV_SYSCALL 40
#define BOOKE_INTERRUPT_HV_PRIV 41
#define BOOKE_INTERRUPT_LRAT_ERROR 42
/* book3s */
......
......@@ -132,8 +132,6 @@ struct slb_shadow {
} save_area[SLB_NUM_BOLTED];
} ____cacheline_aligned;
extern struct slb_shadow slb_shadow[];
/*
* Layout of entries in the hypervisor's dispatch trace log buffer.
*/
......
/*
* Machine check exception header file.
*
* 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.
*
* Copyright 2013 IBM Corporation
* Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
*/
#ifndef __ASM_PPC64_MCE_H__
#define __ASM_PPC64_MCE_H__
#include <linux/bitops.h>
/*
* Machine Check bits on power7 and power8
*/
#define P7_SRR1_MC_LOADSTORE(srr1) ((srr1) & PPC_BIT(42)) /* P8 too */
/* SRR1 bits for machine check (On Power7 and Power8) */
#define P7_SRR1_MC_IFETCH(srr1) ((srr1) & PPC_BITMASK(43, 45)) /* P8 too */
#define P7_SRR1_MC_IFETCH_UE (0x1 << PPC_BITLSHIFT(45)) /* P8 too */
#define P7_SRR1_MC_IFETCH_SLB_PARITY (0x2 << PPC_BITLSHIFT(45)) /* P8 too */
#define P7_SRR1_MC_IFETCH_SLB_MULTIHIT (0x3 << PPC_BITLSHIFT(45)) /* P8 too */
#define P7_SRR1_MC_IFETCH_SLB_BOTH (0x4 << PPC_BITLSHIFT(45))
#define P7_SRR1_MC_IFETCH_TLB_MULTIHIT (0x5 << PPC_BITLSHIFT(45)) /* P8 too */
#define P7_SRR1_MC_IFETCH_UE_TLB_RELOAD (0x6 << PPC_BITLSHIFT(45)) /* P8 too */
#define P7_SRR1_MC_IFETCH_UE_IFU_INTERNAL (0x7 << PPC_BITLSHIFT(45))
/* SRR1 bits for machine check (On Power8) */
#define P8_SRR1_MC_IFETCH_ERAT_MULTIHIT (0x4 << PPC_BITLSHIFT(45))
/* DSISR bits for machine check (On Power7 and Power8) */
#define P7_DSISR_MC_UE (PPC_BIT(48)) /* P8 too */
#define P7_DSISR_MC_UE_TABLEWALK (PPC_BIT(49)) /* P8 too */
#define P7_DSISR_MC_ERAT_MULTIHIT (PPC_BIT(52)) /* P8 too */
#define P7_DSISR_MC_TLB_MULTIHIT_MFTLB (PPC_BIT(53)) /* P8 too */
#define P7_DSISR_MC_SLB_PARITY_MFSLB (PPC_BIT(55)) /* P8 too */
#define P7_DSISR_MC_SLB_MULTIHIT (PPC_BIT(56)) /* P8 too */
#define P7_DSISR_MC_SLB_MULTIHIT_PARITY (PPC_BIT(57)) /* P8 too */
/*
* DSISR bits for machine check (Power8) in addition to above.
* Secondary DERAT Multihit
*/
#define P8_DSISR_MC_ERAT_MULTIHIT_SEC (PPC_BIT(54))
/* SLB error bits */
#define P7_DSISR_MC_SLB_ERRORS (P7_DSISR_MC_ERAT_MULTIHIT | \
P7_DSISR_MC_SLB_PARITY_MFSLB | \
P7_DSISR_MC_SLB_MULTIHIT | \
P7_DSISR_MC_SLB_MULTIHIT_PARITY)
#define P8_DSISR_MC_SLB_ERRORS (P7_DSISR_MC_SLB_ERRORS | \
P8_DSISR_MC_ERAT_MULTIHIT_SEC)
enum MCE_Version {
MCE_V1 = 1,
};
enum MCE_Severity {
MCE_SEV_NO_ERROR = 0,
MCE_SEV_WARNING = 1,
MCE_SEV_ERROR_SYNC = 2,
MCE_SEV_FATAL = 3,
};
enum MCE_Disposition {
MCE_DISPOSITION_RECOVERED = 0,
MCE_DISPOSITION_NOT_RECOVERED = 1,
};
enum MCE_Initiator {
MCE_INITIATOR_UNKNOWN = 0,
MCE_INITIATOR_CPU = 1,
};
enum MCE_ErrorType {
MCE_ERROR_TYPE_UNKNOWN = 0,
MCE_ERROR_TYPE_UE = 1,
MCE_ERROR_TYPE_SLB = 2,
MCE_ERROR_TYPE_ERAT = 3,
MCE_ERROR_TYPE_TLB = 4,
};
enum MCE_UeErrorType {
MCE_UE_ERROR_INDETERMINATE = 0,
MCE_UE_ERROR_IFETCH = 1,
MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
MCE_UE_ERROR_LOAD_STORE = 3,
MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4,
};
enum MCE_SlbErrorType {
MCE_SLB_ERROR_INDETERMINATE = 0,
MCE_SLB_ERROR_PARITY = 1,
MCE_SLB_ERROR_MULTIHIT = 2,
};
enum MCE_EratErrorType {
MCE_ERAT_ERROR_INDETERMINATE = 0,
MCE_ERAT_ERROR_PARITY = 1,
MCE_ERAT_ERROR_MULTIHIT = 2,
};
enum MCE_TlbErrorType {
MCE_TLB_ERROR_INDETERMINATE = 0,
MCE_TLB_ERROR_PARITY = 1,
MCE_TLB_ERROR_MULTIHIT = 2,
};
struct machine_check_event {
enum MCE_Version version:8; /* 0x00 */
uint8_t in_use; /* 0x01 */
enum MCE_Severity severity:8; /* 0x02 */
enum MCE_Initiator initiator:8; /* 0x03 */
enum MCE_ErrorType error_type:8; /* 0x04 */
enum MCE_Disposition disposition:8; /* 0x05 */
uint8_t reserved_1[2]; /* 0x06 */
uint64_t gpr3; /* 0x08 */
uint64_t srr0; /* 0x10 */
uint64_t srr1; /* 0x18 */
union { /* 0x20 */
struct {
enum MCE_UeErrorType ue_error_type:8;
uint8_t effective_address_provided;
uint8_t physical_address_provided;
uint8_t reserved_1[5];
uint64_t effective_address;
uint64_t physical_address;
uint8_t reserved_2[8];
} ue_error;
struct {
enum MCE_SlbErrorType slb_error_type:8;
uint8_t effective_address_provided;
uint8_t reserved_1[6];
uint64_t effective_address;
uint8_t reserved_2[16];
} slb_error;
struct {
enum MCE_EratErrorType erat_error_type:8;
uint8_t effective_address_provided;
uint8_t reserved_1[6];
uint64_t effective_address;
uint8_t reserved_2[16];
} erat_error;
struct {
enum MCE_TlbErrorType tlb_error_type:8;
uint8_t effective_address_provided;
uint8_t reserved_1[6];
uint64_t effective_address;
uint8_t reserved_2[16];
} tlb_error;
} u;
};
struct mce_error_info {
enum MCE_ErrorType error_type:8;
union {
enum MCE_UeErrorType ue_error_type:8;
enum MCE_SlbErrorType slb_error_type:8;
enum MCE_EratErrorType erat_error_type:8;
enum MCE_TlbErrorType tlb_error_type:8;
} u;
uint8_t reserved[2];
};
#define MAX_MC_EVT 100
/* Release flags for get_mce_event() */
#define MCE_EVENT_RELEASE true
#define MCE_EVENT_DONTRELEASE false
extern void save_mce_event(struct pt_regs *regs, long handled,
struct mce_error_info *mce_err, uint64_t addr);
extern int get_mce_event(struct machine_check_event *mce, bool release);
extern void release_mce_event(void);
extern void machine_check_queue_event(void);
extern void machine_check_print_event_info(struct machine_check_event *evt);
extern uint64_t get_mce_fault_addr(struct machine_check_event *evt);
#endif /* __ASM_PPC64_MCE_H__ */
......@@ -286,8 +286,21 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
extern int mmu_linear_psize;
extern int mmu_vmemmap_psize;
struct tlb_core_data {
/* For software way selection, as on Freescale TLB1 */
u8 esel_next, esel_max, esel_first;
/* Per-core spinlock for e6500 TLB handlers (no tlbsrx.) */
u8 lock;
};
#ifdef CONFIG_PPC64
extern unsigned long linear_map_top;
extern int book3e_htw_mode;
#define PPC_HTW_NONE 0
#define PPC_HTW_IBM 1
#define PPC_HTW_E6500 2
/*
* 64-bit booke platforms don't load the tlb in the tlb miss handler code.
......
......@@ -180,16 +180,17 @@ static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
#define MMU_PAGE_64K_AP 3 /* "Admixed pages" (hash64 only) */
#define MMU_PAGE_256K 4
#define MMU_PAGE_1M 5
#define MMU_PAGE_4M 6
#define MMU_PAGE_8M 7
#define MMU_PAGE_16M 8
#define MMU_PAGE_64M 9
#define MMU_PAGE_256M 10
#define MMU_PAGE_1G 11
#define MMU_PAGE_16G 12
#define MMU_PAGE_64G 13
#define MMU_PAGE_COUNT 14
#define MMU_PAGE_2M 6
#define MMU_PAGE_4M 7
#define MMU_PAGE_8M 8
#define MMU_PAGE_16M 9
#define MMU_PAGE_64M 10
#define MMU_PAGE_256M 11
#define MMU_PAGE_1G 12
#define MMU_PAGE_16G 13
#define MMU_PAGE_64G 14
#define MMU_PAGE_COUNT 15
#if defined(CONFIG_PPC_STD_MMU_64)
/* 64-bit classic hash table MMU */
......
......@@ -33,6 +33,28 @@ struct opal_takeover_args {
u64 rd_loc; /* r11 */
};
/*
* SG entry
*
* WARNING: The current implementation requires each entry
* to represent a block that is 4k aligned *and* each block
* size except the last one in the list to be as well.
*/
struct opal_sg_entry {
void *data;
long length;
};
/* sg list */
struct opal_sg_list {
unsigned long num_entries;
struct opal_sg_list *next;
struct opal_sg_entry entry[];
};
/* We calculate number of sg entries based on PAGE_SIZE */
#define SG_ENTRIES_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct opal_sg_entry))
extern long opal_query_takeover(u64 *hal_size, u64 *hal_align);
extern long opal_do_takeover(struct opal_takeover_args *args);
......@@ -132,6 +154,9 @@ extern int opal_enter_rtas(struct rtas_args *args,
#define OPAL_FLASH_VALIDATE 76
#define OPAL_FLASH_MANAGE 77
#define OPAL_FLASH_UPDATE 78
#define OPAL_GET_MSG 85
#define OPAL_CHECK_ASYNC_COMPLETION 86
#define OPAL_SYNC_HOST_REBOOT 87
#ifndef __ASSEMBLY__
......@@ -211,7 +236,16 @@ enum OpalPendingState {
OPAL_EVENT_ERROR_LOG = 0x40,
OPAL_EVENT_EPOW = 0x80,
OPAL_EVENT_LED_STATUS = 0x100,
OPAL_EVENT_PCI_ERROR = 0x200
OPAL_EVENT_PCI_ERROR = 0x200,
OPAL_EVENT_MSG_PENDING = 0x800,
};
enum OpalMessageType {
OPAL_MSG_ASYNC_COMP = 0,
OPAL_MSG_MEM_ERR,
OPAL_MSG_EPOW,
OPAL_MSG_SHUTDOWN,
OPAL_MSG_TYPE_MAX,
};
/* Machine check related definitions */
......@@ -311,12 +345,16 @@ enum OpalMveEnableAction {
OPAL_ENABLE_MVE = 1
};
enum OpalPciResetAndReinitScope {
enum OpalPciResetScope {
OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3,
OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5,
OPAL_PCI_IODA_TABLE_RESET = 6,
};
enum OpalPciReinitScope {
OPAL_REINIT_PCI_DEV = 1000
};
enum OpalPciResetState {
OPAL_DEASSERT_RESET = 0,
OPAL_ASSERT_RESET = 1
......@@ -356,6 +394,12 @@ enum OpalLPCAddressType {
OPAL_LPC_FW = 2,
};
struct opal_msg {
uint32_t msg_type;
uint32_t reserved;
uint64_t params[8];
};
struct opal_machine_check_event {
enum OpalMCE_Version version:8; /* 0x00 */
uint8_t in_use; /* 0x01 */
......@@ -404,6 +448,58 @@ struct opal_machine_check_event {
} u;
};
/* FSP memory errors handling */
enum OpalMemErr_Version {
OpalMemErr_V1 = 1,
};
enum OpalMemErrType {
OPAL_MEM_ERR_TYPE_RESILIENCE = 0,
OPAL_MEM_ERR_TYPE_DYN_DALLOC,
OPAL_MEM_ERR_TYPE_SCRUB,
};
/* Memory Reilience error type */
enum OpalMemErr_ResilErrType {
OPAL_MEM_RESILIENCE_CE = 0,
OPAL_MEM_RESILIENCE_UE,
OPAL_MEM_RESILIENCE_UE_SCRUB,
};
/* Dynamic Memory Deallocation type */
enum OpalMemErr_DynErrType {
OPAL_MEM_DYNAMIC_DEALLOC = 0,
};
/* OpalMemoryErrorData->flags */
#define OPAL_MEM_CORRECTED_ERROR 0x0001
#define OPAL_MEM_THRESHOLD_EXCEEDED 0x0002
#define OPAL_MEM_ACK_REQUIRED 0x8000
struct OpalMemoryErrorData {
enum OpalMemErr_Version version:8; /* 0x00 */
enum OpalMemErrType type:8; /* 0x01 */
uint16_t flags; /* 0x02 */
uint8_t reserved_1[4]; /* 0x04 */
union {
/* Memory Resilience corrected/uncorrected error info */
struct {
enum OpalMemErr_ResilErrType resil_err_type:8;
uint8_t reserved_1[7];
uint64_t physical_address_start;
uint64_t physical_address_end;
} resilience;
/* Dynamic memory deallocation error info */
struct {
enum OpalMemErr_DynErrType dyn_err_type:8;
uint8_t reserved_1[7];
uint64_t physical_address_start;
uint64_t physical_address_end;
} dyn_dealloc;
} u;
};
enum {
OPAL_P7IOC_DIAG_TYPE_NONE = 0,
OPAL_P7IOC_DIAG_TYPE_RGC = 1,
......@@ -710,7 +806,7 @@ int64_t opal_pci_get_phb_diag_data(uint64_t phb_id, void *diag_buffer,
int64_t opal_pci_get_phb_diag_data2(uint64_t phb_id, void *diag_buffer,
uint64_t diag_buffer_len);
int64_t opal_pci_fence_phb(uint64_t phb_id);
int64_t opal_pci_reinit(uint64_t phb_id, uint8_t reinit_scope);
int64_t opal_pci_reinit(uint64_t phb_id, uint64_t reinit_scope, uint64_t data);
int64_t opal_pci_mask_pe_error(uint64_t phb_id, uint16_t pe_number, uint8_t error_type, uint8_t mask_action);
int64_t opal_set_slot_led_status(uint64_t phb_id, uint64_t slot_id, uint8_t led_type, uint8_t led_action);
int64_t opal_get_epow_status(__be64 *status);
......@@ -731,6 +827,10 @@ int64_t opal_validate_flash(uint64_t buffer, uint32_t *size, uint32_t *result);
int64_t opal_manage_flash(uint8_t op);
int64_t opal_update_flash(uint64_t blk_list);
int64_t opal_get_msg(uint64_t buffer, size_t size);
int64_t opal_check_completion(uint64_t buffer, size_t size, uint64_t token);
int64_t opal_sync_host_reboot(void);
/* Internal functions */
extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
......@@ -744,6 +844,8 @@ extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
int depth, void *data);
extern int opal_notifier_register(struct notifier_block *nb);
extern int opal_message_notifier_register(enum OpalMessageType msg_type,
struct notifier_block *nb);
extern void opal_notifier_enable(void);
extern void opal_notifier_disable(void);
extern void opal_notifier_update_evt(uint64_t evt_mask, uint64_t evt_val);
......
......@@ -16,7 +16,6 @@
#ifdef CONFIG_PPC64
#include <linux/init.h>
#include <asm/types.h>
#include <asm/lppaca.h>
#include <asm/mmu.h>
......@@ -113,6 +112,10 @@ struct paca_struct {
/* Keep pgd in the same cacheline as the start of extlb */
pgd_t *pgd __attribute__((aligned(0x80))); /* Current PGD */
pgd_t *kernel_pgd; /* Kernel PGD */
/* Shared by all threads of a core -- points to tcd of first thread */
struct tlb_core_data *tcd_ptr;
/* We can have up to 3 levels of reentrancy in the TLB miss handler */
u64 extlb[3][EX_TLB_SIZE / sizeof(u64)];
u64 exmc[8]; /* used for machine checks */
......@@ -123,6 +126,8 @@ struct paca_struct {
void *mc_kstack;
void *crit_kstack;
void *dbg_kstack;
struct tlb_core_data tcd;
#endif /* CONFIG_PPC_BOOK3E */
mm_context_t context;
......@@ -152,6 +157,15 @@ struct paca_struct {
*/
struct opal_machine_check_event *opal_mc_evt;
#endif
#ifdef CONFIG_PPC_BOOK3S_64
/* Exclusive emergency stack pointer for machine check exception. */
void *mc_emergency_sp;
/*
* Flag to check whether we are in machine check early handler
* and already using emergency stack.
*/
u16 in_mce;
#endif
/* Stuff for accurate time accounting */
u64 user_time; /* accumulated usermode TB ticks */
......
......@@ -3,6 +3,7 @@
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
#include <linux/mmdebug.h>
#include <asm/processor.h> /* For TASK_SIZE */
#include <asm/mmu.h>
#include <asm/page.h>
......@@ -33,10 +34,73 @@ static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; }
static inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; }
static inline pgprot_t pte_pgprot(pte_t pte) { return __pgprot(pte_val(pte) & PAGE_PROT_BITS); }
#ifdef CONFIG_NUMA_BALANCING
static inline int pte_present(pte_t pte)
{
return pte_val(pte) & (_PAGE_PRESENT | _PAGE_NUMA);
}
#define pte_numa pte_numa
static inline int pte_numa(pte_t pte)
{
return (pte_val(pte) &
(_PAGE_NUMA|_PAGE_PRESENT)) == _PAGE_NUMA;
}
#define pte_mknonnuma pte_mknonnuma
static inline pte_t pte_mknonnuma(pte_t pte)
{
pte_val(pte) &= ~_PAGE_NUMA;
pte_val(pte) |= _PAGE_PRESENT | _PAGE_ACCESSED;
return pte;
}
#define pte_mknuma pte_mknuma
static inline pte_t pte_mknuma(pte_t pte)
{
/*
* We should not set _PAGE_NUMA on non present ptes. Also clear the
* present bit so that hash_page will return 1 and we collect this
* as numa fault.
*/
if (pte_present(pte)) {
pte_val(pte) |= _PAGE_NUMA;
pte_val(pte) &= ~_PAGE_PRESENT;
} else
VM_BUG_ON(1);
return pte;
}
#define pmd_numa pmd_numa
static inline int pmd_numa(pmd_t pmd)
{
return pte_numa(pmd_pte(pmd));
}
#define pmd_mknonnuma pmd_mknonnuma
static inline pmd_t pmd_mknonnuma(pmd_t pmd)
{
return pte_pmd(pte_mknonnuma(pmd_pte(pmd)));
}
#define pmd_mknuma pmd_mknuma
static inline pmd_t pmd_mknuma(pmd_t pmd)
{
return pte_pmd(pte_mknuma(pmd_pte(pmd)));
}
# else
static inline int pte_present(pte_t pte)
{
return pte_val(pte) & _PAGE_PRESENT;
}
#endif /* CONFIG_NUMA_BALANCING */
/* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
*
......
......@@ -4,7 +4,6 @@
#ifndef _ASM_POWERPC_PPC_ASM_H
#define _ASM_POWERPC_PPC_ASM_H
#include <linux/init.h>
#include <linux/stringify.h>
#include <asm/asm-compat.h>
#include <asm/processor.h>
......@@ -295,6 +294,11 @@ GLUE(.,name):
* you want to access various offsets within it). On ppc32 this is
* identical to LOAD_REG_IMMEDIATE.
*
* LOAD_REG_ADDR_PIC(rn, name)
* Loads the address of label 'name' into register 'run'. Use this when
* the kernel doesn't run at the linked or relocated address. Please
* note that this macro will clobber the lr register.
*
* LOAD_REG_ADDRBASE(rn, name)
* ADDROFF(name)
* LOAD_REG_ADDRBASE loads part of the address of label 'name' into
......@@ -305,6 +309,14 @@ GLUE(.,name):
* LOAD_REG_ADDRBASE(rX, name)
* ld rY,ADDROFF(name)(rX)
*/
/* Be careful, this will clobber the lr register. */
#define LOAD_REG_ADDR_PIC(reg, name) \
bl 0f; \
0: mflr reg; \
addis reg,reg,(name - 0b)@ha; \
addi reg,reg,(name - 0b)@l;
#ifdef __powerpc64__
#define LOAD_REG_IMMEDIATE(reg,expr) \
lis reg,(expr)@highest; \
......
......@@ -256,6 +256,8 @@ struct thread_struct {
unsigned long evr[32]; /* upper 32-bits of SPE regs */
u64 acc; /* Accumulator */
unsigned long spefscr; /* SPE & eFP status */
unsigned long spefscr_last; /* SPEFSCR value on last prctl
call or trap return */
int used_spe; /* set if process has used spe */
#endif /* CONFIG_SPE */
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
......@@ -317,7 +319,9 @@ struct thread_struct {
(_ALIGN_UP(sizeof(init_thread_info), 16) + (unsigned long) &init_stack)
#ifdef CONFIG_SPE
#define SPEFSCR_INIT .spefscr = SPEFSCR_FINVE | SPEFSCR_FDBZE | SPEFSCR_FUNFE | SPEFSCR_FOVFE,
#define SPEFSCR_INIT \
.spefscr = SPEFSCR_FINVE | SPEFSCR_FDBZE | SPEFSCR_FUNFE | SPEFSCR_FOVFE, \
.spefscr_last = SPEFSCR_FINVE | SPEFSCR_FDBZE | SPEFSCR_FUNFE | SPEFSCR_FOVFE,
#else
#define SPEFSCR_INIT
#endif
......@@ -373,6 +377,8 @@ extern int set_endian(struct task_struct *tsk, unsigned int val);
extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr);
extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
extern void fp_enable(void);
extern void vec_enable(void);
extern void load_fp_state(struct thread_fp_state *fp);
extern void store_fp_state(struct thread_fp_state *fp);
extern void load_vr_state(struct thread_vr_state *vr);
......
......@@ -21,7 +21,6 @@
#if !defined(_ASM_POWERPC_PS3_H)
#define _ASM_POWERPC_PS3_H
#include <linux/init.h>
#include <linux/types.h>
#include <linux/device.h>
#include <asm/cell-pmu.h>
......
......@@ -19,7 +19,7 @@
#define _PAGE_FILE 0x0002 /* (!present only) software: pte holds file offset */
#define _PAGE_EXEC 0x0004 /* No execute on POWER4 and newer (we invert) */
#define _PAGE_GUARDED 0x0008
#define _PAGE_COHERENT 0x0010 /* M: enforce memory coherence (SMP systems) */
/* We can derive Memory coherence from _PAGE_NO_CACHE */
#define _PAGE_NO_CACHE 0x0020 /* I: cache inhibit */
#define _PAGE_WRITETHRU 0x0040 /* W: cache write-through */
#define _PAGE_DIRTY 0x0080 /* C: page changed */
......@@ -27,6 +27,12 @@
#define _PAGE_RW 0x0200 /* software: user write access allowed */
#define _PAGE_BUSY 0x0800 /* software: PTE & hash are busy */
/*
* Used for tracking numa faults
*/
#define _PAGE_NUMA 0x00000010 /* Gather numa placement stats */
/* No separate kernel read-only */
#define _PAGE_KERNEL_RW (_PAGE_RW | _PAGE_DIRTY) /* user access blocked by key */
#define _PAGE_KERNEL_RO _PAGE_KERNEL_RW
......
......@@ -1075,6 +1075,8 @@
#define PVR_8560 0x80200000
#define PVR_VER_E500V1 0x8020
#define PVR_VER_E500V2 0x8021
#define PVR_VER_E6500 0x8040
/*
* For the 8xx processors, all of them report the same PVR family for
* the PowerPC core. The various versions of these processors must be
......
......@@ -101,6 +101,7 @@
#define SPRN_IVOR39 0x1B1 /* Interrupt Vector Offset Register 39 */
#define SPRN_IVOR40 0x1B2 /* Interrupt Vector Offset Register 40 */
#define SPRN_IVOR41 0x1B3 /* Interrupt Vector Offset Register 41 */
#define SPRN_IVOR42 0x1B4 /* Interrupt Vector Offset Register 42 */
#define SPRN_GIVOR2 0x1B8 /* Guest IVOR2 */
#define SPRN_GIVOR3 0x1B9 /* Guest IVOR3 */
#define SPRN_GIVOR4 0x1BA /* Guest IVOR4 */
......@@ -170,6 +171,7 @@
#define SPRN_L2CSR1 0x3FA /* L2 Data Cache Control and Status Register 1 */
#define SPRN_DCCR 0x3FA /* Data Cache Cacheability Register */
#define SPRN_ICCR 0x3FB /* Instruction Cache Cacheability Register */
#define SPRN_PWRMGTCR0 0x3FB /* Power management control register 0 */
#define SPRN_SVR 0x3FF /* System Version Register */
/*
......@@ -216,6 +218,14 @@
#define CCR1_DPC 0x00000100 /* Disable L1 I-Cache/D-Cache parity checking */
#define CCR1_TCS 0x00000080 /* Timer Clock Select */
/* Bit definitions for PWRMGTCR0. */
#define PWRMGTCR0_PW20_WAIT (1 << 14) /* PW20 state enable bit */
#define PWRMGTCR0_PW20_ENT_SHIFT 8
#define PWRMGTCR0_PW20_ENT 0x3F00
#define PWRMGTCR0_AV_IDLE_PD_EN (1 << 22) /* Altivec idle enable */
#define PWRMGTCR0_AV_IDLE_CNT_SHIFT 16
#define PWRMGTCR0_AV_IDLE_CNT 0x3F0000
/* Bit definitions for the MCSR. */
#define MCSR_MCS 0x80000000 /* Machine Check Summary */
#define MCSR_IB 0x40000000 /* Instruction PLB Error */
......
......@@ -30,8 +30,6 @@
#define smp_mb__after_unlock_lock() smp_mb() /* Full ordering for lock. */
#define arch_spin_is_locked(x) ((x)->slock != 0)
#ifdef CONFIG_PPC64
/* use 0x800000yy when locked, where yy == CPU number */
#ifdef __BIG_ENDIAN__
......@@ -56,6 +54,16 @@
#define SYNC_IO
#endif
static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock)
{
return lock.slock == 0;
}
static inline int arch_spin_is_locked(arch_spinlock_t *lock)
{
return !arch_spin_value_unlocked(*lock);
}
/*
* This returns the old value in the lock, so we succeeded
* in getting the lock if the return value is 0.
......
......@@ -91,8 +91,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_POLLING_NRFLAG 3 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
#define TIF_32BIT 4 /* 32 bit binary */
#define TIF_PERFMON_WORK 5 /* work for pfm_handle_work() */
#define TIF_PERFMON_CTXSW 6 /* perfmon needs ctxsw calls */
#define TIF_RESTORE_TM 5 /* need to restore TM FP/VEC/VSX */
#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
#define TIF_SINGLESTEP 8 /* singlestepping active */
#define TIF_NOHZ 9 /* in adaptive nohz mode */
......@@ -115,8 +114,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_32BIT (1<<TIF_32BIT)
#define _TIF_PERFMON_WORK (1<<TIF_PERFMON_WORK)
#define _TIF_PERFMON_CTXSW (1<<TIF_PERFMON_CTXSW)
#define _TIF_RESTORE_TM (1<<TIF_RESTORE_TM)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
......@@ -132,7 +130,8 @@ static inline struct thread_info *current_thread_info(void)
_TIF_NOHZ)
#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
_TIF_NOTIFY_RESUME | _TIF_UPROBE)
_TIF_NOTIFY_RESUME | _TIF_UPROBE | \
_TIF_RESTORE_TM)
#define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR)
/* Bits in local_flags */
......
......@@ -15,6 +15,7 @@ extern void do_load_up_transact_altivec(struct thread_struct *thread);
extern void tm_enable(void);
extern void tm_reclaim(struct thread_struct *thread,
unsigned long orig_msr, uint8_t cause);
extern void tm_reclaim_current(uint8_t cause);
extern void tm_recheckpoint(struct thread_struct *thread,
unsigned long orig_msr);
extern void tm_abort(uint8_t cause);
......
......@@ -22,7 +22,15 @@ struct device_node;
static inline int cpu_to_node(int cpu)
{
return numa_cpu_lookup_table[cpu];
int nid;
nid = numa_cpu_lookup_table[cpu];
/*
* During early boot, the numa-cpu lookup table might not have been
* setup for all CPUs yet. In such cases, default to node 0.
*/
return (nid < 0) ? 0 : nid;
}
#define parent_node(node) (node)
......
......@@ -15,7 +15,6 @@
#define _ASM_POWERPC_VIO_H
#ifdef __KERNEL__
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
......
......@@ -39,6 +39,7 @@ obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_ppc970.o cpu_setup_pa6t.o
obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_power.o
obj-$(CONFIG_PPC_BOOK3S_64) += mce.o mce_power.o
obj64-$(CONFIG_RELOCATABLE) += reloc_64.o
obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o idle_book3e.o
obj-$(CONFIG_PPC_A2) += cpu_setup_a2.o
......
......@@ -203,6 +203,15 @@ int main(void)
DEFINE(PACA_MC_STACK, offsetof(struct paca_struct, mc_kstack));
DEFINE(PACA_CRIT_STACK, offsetof(struct paca_struct, crit_kstack));
DEFINE(PACA_DBG_STACK, offsetof(struct paca_struct, dbg_kstack));
DEFINE(PACA_TCD_PTR, offsetof(struct paca_struct, tcd_ptr));
DEFINE(TCD_ESEL_NEXT,
offsetof(struct tlb_core_data, esel_next));
DEFINE(TCD_ESEL_MAX,
offsetof(struct tlb_core_data, esel_max));
DEFINE(TCD_ESEL_FIRST,
offsetof(struct tlb_core_data, esel_first));
DEFINE(TCD_LOCK, offsetof(struct tlb_core_data, lock));
#endif /* CONFIG_PPC_BOOK3E */
#ifdef CONFIG_PPC_STD_MMU_64
......@@ -232,6 +241,10 @@ int main(void)
DEFINE(PACA_DTL_RIDX, offsetof(struct paca_struct, dtl_ridx));
#endif /* CONFIG_PPC_STD_MMU_64 */
DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
#ifdef CONFIG_PPC_BOOK3S_64
DEFINE(PACAMCEMERGSP, offsetof(struct paca_struct, mc_emergency_sp));
DEFINE(PACA_IN_MCE, offsetof(struct paca_struct, in_mce));
#endif
DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state));
DEFINE(PACA_STARTTIME, offsetof(struct paca_struct, starttime));
......
......@@ -12,7 +12,6 @@
#include <linux/cpu.h>
#include <linux/cpumask.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/list.h>
......
......@@ -53,11 +53,57 @@ _GLOBAL(__e500_dcache_setup)
isync
blr
/*
* FIXME - we haven't yet done testing to determine a reasonable default
* value for PW20_WAIT_IDLE_BIT.
*/
#define PW20_WAIT_IDLE_BIT 50 /* 1ms, TB frequency is 41.66MHZ */
_GLOBAL(setup_pw20_idle)
mfspr r3, SPRN_PWRMGTCR0
/* Set PW20_WAIT bit, enable pw20 state*/
ori r3, r3, PWRMGTCR0_PW20_WAIT
li r11, PW20_WAIT_IDLE_BIT
/* Set Automatic PW20 Core Idle Count */
rlwimi r3, r11, PWRMGTCR0_PW20_ENT_SHIFT, PWRMGTCR0_PW20_ENT
mtspr SPRN_PWRMGTCR0, r3
blr
/*
* FIXME - we haven't yet done testing to determine a reasonable default
* value for AV_WAIT_IDLE_BIT.
*/
#define AV_WAIT_IDLE_BIT 50 /* 1ms, TB frequency is 41.66MHZ */
_GLOBAL(setup_altivec_idle)
mfspr r3, SPRN_PWRMGTCR0
/* Enable Altivec Idle */
oris r3, r3, PWRMGTCR0_AV_IDLE_PD_EN@h
li r11, AV_WAIT_IDLE_BIT
/* Set Automatic AltiVec Idle Count */
rlwimi r3, r11, PWRMGTCR0_AV_IDLE_CNT_SHIFT, PWRMGTCR0_AV_IDLE_CNT
mtspr SPRN_PWRMGTCR0, r3
blr
_GLOBAL(__setup_cpu_e6500)
mflr r6
#ifdef CONFIG_PPC64
bl .setup_altivec_ivors
/* Touch IVOR42 only if the CPU supports E.HV category */
mfspr r10,SPRN_MMUCFG
rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
beq 1f
bl .setup_lrat_ivor
1:
#endif
bl setup_pw20_idle
bl setup_altivec_idle
bl __setup_cpu_e5500
mtlr r6
blr
......@@ -119,6 +165,14 @@ _GLOBAL(__setup_cpu_e5500)
_GLOBAL(__restore_cpu_e6500)
mflr r5
bl .setup_altivec_ivors
/* Touch IVOR42 only if the CPU supports E.HV category */
mfspr r10,SPRN_MMUCFG
rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
beq 1f
bl .setup_lrat_ivor
1:
bl .setup_pw20_idle
bl .setup_altivec_idle
bl __restore_cpu_e5500
mtlr r5
blr
......
......@@ -29,7 +29,7 @@ _GLOBAL(__setup_cpu_power7)
mtspr SPRN_LPID,r0
mfspr r3,SPRN_LPCR
bl __init_LPCR
bl __init_TLB
bl __init_tlb_power7
mtlr r11
blr
......@@ -42,7 +42,7 @@ _GLOBAL(__restore_cpu_power7)
mtspr SPRN_LPID,r0
mfspr r3,SPRN_LPCR
bl __init_LPCR
bl __init_TLB
bl __init_tlb_power7
mtlr r11
blr
......@@ -59,7 +59,7 @@ _GLOBAL(__setup_cpu_power8)
oris r3, r3, LPCR_AIL_3@h
bl __init_LPCR
bl __init_HFSCR
bl __init_TLB
bl __init_tlb_power8
bl __init_PMU_HV
mtlr r11
blr
......@@ -78,7 +78,7 @@ _GLOBAL(__restore_cpu_power8)
oris r3, r3, LPCR_AIL_3@h
bl __init_LPCR
bl __init_HFSCR
bl __init_TLB
bl __init_tlb_power8
bl __init_PMU_HV
mtlr r11
blr
......@@ -134,15 +134,31 @@ __init_HFSCR:
mtspr SPRN_HFSCR,r3
blr
__init_TLB:
/*
* Clear the TLB using the "IS 3" form of tlbiel instruction
* (invalidate by congruence class). P7 has 128 CCs, P8 has 512
* so we just always do 512
*/
/*
* Clear the TLB using the specified IS form of tlbiel instruction
* (invalidate by congruence class). P7 has 128 CCs., P8 has 512.
*
* r3 = IS field
*/
__init_tlb_power7:
li r3,0xc00 /* IS field = 0b11 */
_GLOBAL(__flush_tlb_power7)
li r6,128
mtctr r6
mr r7,r3 /* IS field */
ptesync
2: tlbiel r7
addi r7,r7,0x1000
bdnz 2b
ptesync
1: blr
__init_tlb_power8:
li r3,0xc00 /* IS field = 0b11 */
_GLOBAL(__flush_tlb_power8)
li r6,512
mtctr r6
li r7,0xc00 /* IS field = 0b11 */
mr r7,r3 /* IS field */
ptesync
2: tlbiel r7
addi r7,r7,0x1000
......
......@@ -71,6 +71,10 @@ extern void __restore_cpu_power7(void);
extern void __setup_cpu_power8(unsigned long offset, struct cpu_spec* spec);
extern void __restore_cpu_power8(void);
extern void __restore_cpu_a2(void);
extern void __flush_tlb_power7(unsigned long inval_selector);
extern void __flush_tlb_power8(unsigned long inval_selector);
extern long __machine_check_early_realmode_p7(struct pt_regs *regs);
extern long __machine_check_early_realmode_p8(struct pt_regs *regs);
#endif /* CONFIG_PPC64 */
#if defined(CONFIG_E500)
extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
......@@ -440,6 +444,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
.oprofile_cpu_type = "ppc64/ibm-compat-v1",
.cpu_setup = __setup_cpu_power7,
.cpu_restore = __restore_cpu_power7,
.flush_tlb = __flush_tlb_power7,
.machine_check_early = __machine_check_early_realmode_p7,
.platform = "power7",
},
{ /* 2.07-compliant processor, i.e. Power8 "architected" mode */
......@@ -456,6 +462,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
.oprofile_cpu_type = "ppc64/ibm-compat-v1",
.cpu_setup = __setup_cpu_power8,
.cpu_restore = __restore_cpu_power8,
.flush_tlb = __flush_tlb_power8,
.machine_check_early = __machine_check_early_realmode_p8,
.platform = "power8",
},
{ /* Power7 */
......@@ -474,6 +482,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
.oprofile_type = PPC_OPROFILE_POWER4,
.cpu_setup = __setup_cpu_power7,
.cpu_restore = __restore_cpu_power7,
.flush_tlb = __flush_tlb_power7,
.machine_check_early = __machine_check_early_realmode_p7,
.platform = "power7",
},
{ /* Power7+ */
......@@ -492,6 +502,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
.oprofile_type = PPC_OPROFILE_POWER4,
.cpu_setup = __setup_cpu_power7,
.cpu_restore = __restore_cpu_power7,
.flush_tlb = __flush_tlb_power7,
.machine_check_early = __machine_check_early_realmode_p7,
.platform = "power7+",
},
{ /* Power8E */
......@@ -510,6 +522,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
.oprofile_type = PPC_OPROFILE_INVALID,
.cpu_setup = __setup_cpu_power8,
.cpu_restore = __restore_cpu_power8,
.flush_tlb = __flush_tlb_power8,
.machine_check_early = __machine_check_early_realmode_p8,
.platform = "power8",
},
{ /* Power8 */
......@@ -528,6 +542,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
.oprofile_type = PPC_OPROFILE_INVALID,
.cpu_setup = __setup_cpu_power8,
.cpu_restore = __restore_cpu_power8,
.flush_tlb = __flush_tlb_power8,
.machine_check_early = __machine_check_early_realmode_p8,
.platform = "power8",
},
{ /* Cell Broadband Engine */
......
......@@ -17,7 +17,6 @@
#include <linux/export.h>
#include <linux/crash_dump.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/types.h>
......
......@@ -83,10 +83,10 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask)
return 0;
}
if (tbl->it_offset > (mask >> IOMMU_PAGE_SHIFT)) {
if (tbl->it_offset > (mask >> tbl->it_page_shift)) {
dev_info(dev, "Warning: IOMMU offset too big for device mask\n");
dev_info(dev, "mask: 0x%08llx, table offset: 0x%08lx\n",
mask, tbl->it_offset << IOMMU_PAGE_SHIFT);
mask, tbl->it_offset << tbl->it_page_shift);
return 0;
} else
return 1;
......
......@@ -84,7 +84,7 @@
#define EEH_MAX_FAILS 2100000
/* Time to wait for a PCI slot to report status, in milliseconds */
#define PCI_BUS_RESET_WAIT_MSEC (60*1000)
#define PCI_BUS_RESET_WAIT_MSEC (5*60*1000)
/* Platform dependent EEH operations */
struct eeh_ops *eeh_ops = NULL;
......@@ -921,6 +921,13 @@ void eeh_add_device_late(struct pci_dev *dev)
eeh_sysfs_remove_device(edev->pdev);
edev->mode &= ~EEH_DEV_SYSFS;
/*
* We definitely should have the PCI device removed
* though it wasn't correctly. So we needn't call
* into error handler afterwards.
*/
edev->mode |= EEH_DEV_NO_HANDLER;
edev->pdev = NULL;
dev->dev.archdata.edev = NULL;
}
......@@ -1023,6 +1030,14 @@ void eeh_remove_device(struct pci_dev *dev)
else
edev->mode |= EEH_DEV_DISCONNECTED;
/*
* We're removing from the PCI subsystem, that means
* the PCI device driver can't support EEH or not
* well. So we rely on hotplug completely to do recovery
* for the specific PCI device.
*/
edev->mode |= EEH_DEV_NO_HANDLER;
eeh_addr_cache_rmv_dev(dev);
eeh_sysfs_remove_device(dev);
edev->mode &= ~EEH_DEV_SYSFS;
......
......@@ -217,7 +217,8 @@ static void *eeh_report_mmio_enabled(void *data, void *userdata)
if (!driver) return NULL;
if (!driver->err_handler ||
!driver->err_handler->mmio_enabled) {
!driver->err_handler->mmio_enabled ||
(edev->mode & EEH_DEV_NO_HANDLER)) {
eeh_pcid_put(dev);
return NULL;
}
......@@ -258,7 +259,8 @@ static void *eeh_report_reset(void *data, void *userdata)
eeh_enable_irq(dev);
if (!driver->err_handler ||
!driver->err_handler->slot_reset) {
!driver->err_handler->slot_reset ||
(edev->mode & EEH_DEV_NO_HANDLER)) {
eeh_pcid_put(dev);
return NULL;
}
......@@ -297,7 +299,9 @@ static void *eeh_report_resume(void *data, void *userdata)
eeh_enable_irq(dev);
if (!driver->err_handler ||
!driver->err_handler->resume) {
!driver->err_handler->resume ||
(edev->mode & EEH_DEV_NO_HANDLER)) {
edev->mode &= ~EEH_DEV_NO_HANDLER;
eeh_pcid_put(dev);
return NULL;
}
......@@ -476,7 +480,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
/* The longest amount of time to wait for a pci device
* to come back on line, in seconds.
*/
#define MAX_WAIT_FOR_RECOVERY 150
#define MAX_WAIT_FOR_RECOVERY 300
static void eeh_handle_normal_event(struct eeh_pe *pe)
{
......@@ -637,86 +641,92 @@ static void eeh_handle_special_event(void)
{
struct eeh_pe *pe, *phb_pe;
struct pci_bus *bus;
struct pci_controller *hose, *tmp;
struct pci_controller *hose;
unsigned long flags;
int rc = 0;
int rc;
/*
* The return value from next_error() has been classified as follows.
* It might be good to enumerate them. However, next_error() is only
* supported by PowerNV platform for now. So it would be fine to use
* integer directly:
*
* 4 - Dead IOC 3 - Dead PHB
* 2 - Fenced PHB 1 - Frozen PE
* 0 - No error found
*
*/
rc = eeh_ops->next_error(&pe);
if (rc <= 0)
return;
switch (rc) {
case 4:
/* Mark all PHBs in dead state */
eeh_serialize_lock(&flags);
list_for_each_entry_safe(hose, tmp,
&hose_list, list_node) {
phb_pe = eeh_phb_pe_get(hose);
if (!phb_pe) continue;
eeh_pe_state_mark(phb_pe,
EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
do {
rc = eeh_ops->next_error(&pe);
switch (rc) {
case EEH_NEXT_ERR_DEAD_IOC:
/* Mark all PHBs in dead state */
eeh_serialize_lock(&flags);
/* Purge all events */
eeh_remove_event(NULL);
list_for_each_entry(hose, &hose_list, list_node) {
phb_pe = eeh_phb_pe_get(hose);
if (!phb_pe) continue;
eeh_pe_state_mark(phb_pe,
EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
}
eeh_serialize_unlock(flags);
break;
case EEH_NEXT_ERR_FROZEN_PE:
case EEH_NEXT_ERR_FENCED_PHB:
case EEH_NEXT_ERR_DEAD_PHB:
/* Mark the PE in fenced state */
eeh_serialize_lock(&flags);
/* Purge all events of the PHB */
eeh_remove_event(pe);
if (rc == EEH_NEXT_ERR_DEAD_PHB)
eeh_pe_state_mark(pe,
EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
else
eeh_pe_state_mark(pe,
EEH_PE_ISOLATED | EEH_PE_RECOVERING);
eeh_serialize_unlock(flags);
break;
case EEH_NEXT_ERR_NONE:
return;
default:
pr_warn("%s: Invalid value %d from next_error()\n",
__func__, rc);
return;
}
eeh_serialize_unlock(flags);
/* Purge all events */
eeh_remove_event(NULL);
break;
case 3:
case 2:
case 1:
/* Mark the PE in fenced state */
eeh_serialize_lock(&flags);
if (rc == 3)
eeh_pe_state_mark(pe,
EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
else
eeh_pe_state_mark(pe,
EEH_PE_ISOLATED | EEH_PE_RECOVERING);
eeh_serialize_unlock(flags);
/* Purge all events of the PHB */
eeh_remove_event(pe);
break;
default:
pr_err("%s: Invalid value %d from next_error()\n",
__func__, rc);
return;
}
/*
* For fenced PHB and frozen PE, it's handled as normal
* event. We have to remove the affected PHBs for dead
* PHB and IOC
*/
if (rc == 2 || rc == 1)
eeh_handle_normal_event(pe);
else {
pci_lock_rescan_remove();
list_for_each_entry_safe(hose, tmp,
&hose_list, list_node) {
phb_pe = eeh_phb_pe_get(hose);
if (!phb_pe || !(phb_pe->state & EEH_PE_PHB_DEAD))
continue;
bus = eeh_pe_bus_get(phb_pe);
/* Notify all devices that they're about to go down. */
eeh_pe_dev_traverse(pe, eeh_report_failure, NULL);
pcibios_remove_pci_devices(bus);
/*
* For fenced PHB and frozen PE, it's handled as normal
* event. We have to remove the affected PHBs for dead
* PHB and IOC
*/
if (rc == EEH_NEXT_ERR_FROZEN_PE ||
rc == EEH_NEXT_ERR_FENCED_PHB) {
eeh_handle_normal_event(pe);
} else {
pci_lock_rescan_remove();
list_for_each_entry(hose, &hose_list, list_node) {
phb_pe = eeh_phb_pe_get(hose);
if (!phb_pe ||
!(phb_pe->state & EEH_PE_PHB_DEAD))
continue;
/* Notify all devices to be down */
bus = eeh_pe_bus_get(phb_pe);
eeh_pe_dev_traverse(pe,
eeh_report_failure, NULL);
pcibios_remove_pci_devices(bus);
}
pci_unlock_rescan_remove();
}
pci_unlock_rescan_remove();
}
/*
* If we have detected dead IOC, we needn't proceed
* any more since all PHBs would have been removed
*/
if (rc == EEH_NEXT_ERR_DEAD_IOC)
break;
} while (rc != EEH_NEXT_ERR_NONE);
}
/**
......
......@@ -25,7 +25,6 @@
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/gfp.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/string.h>
......@@ -737,6 +736,9 @@ static void *eeh_restore_one_device_bars(void *data, void *flag)
else
eeh_restore_device_bars(edev, dn);
if (eeh_ops->restore_config)
eeh_ops->restore_config(dn);
return NULL;
}
......
......@@ -664,8 +664,16 @@ _GLOBAL(ret_from_except_lite)
bl .restore_interrupts
SCHEDULE_USER
b .ret_from_except_lite
2: bl .save_nvgprs
2:
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
andi. r0,r4,_TIF_USER_WORK_MASK & ~_TIF_RESTORE_TM
bne 3f /* only restore TM if nothing else to do */
addi r3,r1,STACK_FRAME_OVERHEAD
bl .restore_tm_state
b restore
3:
#endif
bl .save_nvgprs
bl .restore_interrupts
addi r3,r1,STACK_FRAME_OVERHEAD
bl .do_notify_resume
......
......@@ -308,6 +308,7 @@ interrupt_base_book3e: /* fake trap */
EXCEPTION_STUB(0x2e0, guest_doorbell_crit)
EXCEPTION_STUB(0x300, hypercall)
EXCEPTION_STUB(0x320, ehpriv)
EXCEPTION_STUB(0x340, lrat_error)
.globl interrupt_end_book3e
interrupt_end_book3e:
......@@ -677,6 +678,17 @@ kernel_dbg_exc:
bl .unknown_exception
b .ret_from_except
/* LRAT Error interrupt */
START_EXCEPTION(lrat_error);
NORMAL_EXCEPTION_PROLOG(0x340, BOOKE_INTERRUPT_LRAT_ERROR,
PROLOG_ADDITION_NONE)
EXCEPTION_COMMON(0x340, PACA_EXGEN, INTS_KEEP)
addi r3,r1,STACK_FRAME_OVERHEAD
bl .save_nvgprs
INTS_RESTORE_HARD
bl .unknown_exception
b .ret_from_except
/*
* An interrupt came in while soft-disabled; We mark paca->irq_happened
* accordingly and if the interrupt is level sensitive, we hard disable
......@@ -859,6 +871,7 @@ BAD_STACK_TRAMPOLINE(0x2e0)
BAD_STACK_TRAMPOLINE(0x300)
BAD_STACK_TRAMPOLINE(0x310)
BAD_STACK_TRAMPOLINE(0x320)
BAD_STACK_TRAMPOLINE(0x340)
BAD_STACK_TRAMPOLINE(0x400)
BAD_STACK_TRAMPOLINE(0x500)
BAD_STACK_TRAMPOLINE(0x600)
......@@ -1055,12 +1068,9 @@ skpinv: addi r6,r6,1 /* Increment */
mtspr SPRN_MAS0,r3
tlbre
mfspr r6,SPRN_MAS1
rlwinm r6,r6,0,2,0 /* clear IPROT */
rlwinm r6,r6,0,2,31 /* clear IPROT and VALID */
mtspr SPRN_MAS1,r6
tlbwe
/* Invalidate TLB1 */
PPC_TLBILX_ALL(0,R0)
sync
isync
......@@ -1114,12 +1124,9 @@ skpinv: addi r6,r6,1 /* Increment */
mtspr SPRN_MAS0,r4
tlbre
mfspr r5,SPRN_MAS1
rlwinm r5,r5,0,2,0 /* clear IPROT */
rlwinm r5,r5,0,2,31 /* clear IPROT and VALID */
mtspr SPRN_MAS1,r5
tlbwe
/* Invalidate TLB1 */
PPC_TLBILX_ALL(0,R0)
sync
isync
......@@ -1414,3 +1421,7 @@ _GLOBAL(setup_ehv_ivors)
SET_IVOR(38, 0x2c0) /* Guest Processor Doorbell */
SET_IVOR(39, 0x2e0) /* Guest Processor Doorbell Crit/MC */
blr
_GLOBAL(setup_lrat_ivor)
SET_IVOR(42, 0x340) /* LRAT Error */
blr
......@@ -155,8 +155,30 @@ machine_check_pSeries_1:
*/
HMT_MEDIUM_PPR_DISCARD
SET_SCRATCH0(r13) /* save r13 */
#ifdef CONFIG_PPC_P7_NAP
BEGIN_FTR_SECTION
/* Running native on arch 2.06 or later, check if we are
* waking up from nap. We only handle no state loss and
* supervisor state loss. We do -not- handle hypervisor
* state loss at this time.
*/
mfspr r13,SPRN_SRR1
rlwinm. r13,r13,47-31,30,31
beq 9f
/* waking up from powersave (nap) state */
cmpwi cr1,r13,2
/* Total loss of HV state is fatal. let's just stay stuck here */
bgt cr1,.
9:
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
#endif /* CONFIG_PPC_P7_NAP */
EXCEPTION_PROLOG_0(PACA_EXMC)
BEGIN_FTR_SECTION
b machine_check_pSeries_early
FTR_SECTION_ELSE
b machine_check_pSeries_0
ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
. = 0x300
.globl data_access_pSeries
......@@ -405,6 +427,64 @@ denorm_exception_hv:
.align 7
/* moved from 0x200 */
machine_check_pSeries_early:
BEGIN_FTR_SECTION
EXCEPTION_PROLOG_1(PACA_EXMC, NOTEST, 0x200)
/*
* Register contents:
* R13 = PACA
* R9 = CR
* Original R9 to R13 is saved on PACA_EXMC
*
* Switch to mc_emergency stack and handle re-entrancy (though we
* currently don't test for overflow). Save MCE registers srr1,
* srr0, dar and dsisr and then set ME=1
*
* We use paca->in_mce to check whether this is the first entry or
* nested machine check. We increment paca->in_mce to track nested
* machine checks.
*
* If this is the first entry then set stack pointer to
* paca->mc_emergency_sp, otherwise r1 is already pointing to
* stack frame on mc_emergency stack.
*
* NOTE: We are here with MSR_ME=0 (off), which means we risk a
* checkstop if we get another machine check exception before we do
* rfid with MSR_ME=1.
*/
mr r11,r1 /* Save r1 */
lhz r10,PACA_IN_MCE(r13)
cmpwi r10,0 /* Are we in nested machine check */
bne 0f /* Yes, we are. */
/* First machine check entry */
ld r1,PACAMCEMERGSP(r13) /* Use MC emergency stack */
0: subi r1,r1,INT_FRAME_SIZE /* alloc stack frame */
addi r10,r10,1 /* increment paca->in_mce */
sth r10,PACA_IN_MCE(r13)
std r11,GPR1(r1) /* Save r1 on the stack. */
std r11,0(r1) /* make stack chain pointer */
mfspr r11,SPRN_SRR0 /* Save SRR0 */
std r11,_NIP(r1)
mfspr r11,SPRN_SRR1 /* Save SRR1 */
std r11,_MSR(r1)
mfspr r11,SPRN_DAR /* Save DAR */
std r11,_DAR(r1)
mfspr r11,SPRN_DSISR /* Save DSISR */
std r11,_DSISR(r1)
std r9,_CCR(r1) /* Save CR in stackframe */
/* Save r9 through r13 from EXMC save area to stack frame. */
EXCEPTION_PROLOG_COMMON_2(PACA_EXMC)
mfmsr r11 /* get MSR value */
ori r11,r11,MSR_ME /* turn on ME bit */
ori r11,r11,MSR_RI /* turn on RI bit */
ld r12,PACAKBASE(r13) /* get high part of &label */
LOAD_HANDLER(r12, machine_check_handle_early)
mtspr SPRN_SRR0,r12
mtspr SPRN_SRR1,r11
rfid
b . /* prevent speculative execution */
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
machine_check_pSeries:
.globl machine_check_fwnmi
machine_check_fwnmi:
......@@ -688,30 +768,6 @@ kvmppc_skip_Hinterrupt:
STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception)
/*
* Machine check is different because we use a different
* save area: PACA_EXMC instead of PACA_EXGEN.
*/
.align 7
.globl machine_check_common
machine_check_common:
mfspr r10,SPRN_DAR
std r10,PACA_EXGEN+EX_DAR(r13)
mfspr r10,SPRN_DSISR
stw r10,PACA_EXGEN+EX_DSISR(r13)
EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
FINISH_NAP
DISABLE_INTS
ld r3,PACA_EXGEN+EX_DAR(r13)
lwz r4,PACA_EXGEN+EX_DSISR(r13)
std r3,_DAR(r1)
std r4,_DSISR(r1)
bl .save_nvgprs
addi r3,r1,STACK_FRAME_OVERHEAD
bl .machine_check_exception
b .ret_from_except
STD_EXCEPTION_COMMON_ASYNC(0x500, hardware_interrupt, do_IRQ)
STD_EXCEPTION_COMMON_ASYNC(0x900, decrementer, .timer_interrupt)
STD_EXCEPTION_COMMON(0x980, hdecrementer, .hdec_interrupt)
......@@ -1080,6 +1136,30 @@ unrecov_user_slb:
#endif /* __DISABLED__ */
/*
* Machine check is different because we use a different
* save area: PACA_EXMC instead of PACA_EXGEN.
*/
.align 7
.globl machine_check_common
machine_check_common:
mfspr r10,SPRN_DAR
std r10,PACA_EXGEN+EX_DAR(r13)
mfspr r10,SPRN_DSISR
stw r10,PACA_EXGEN+EX_DSISR(r13)
EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
FINISH_NAP
DISABLE_INTS
ld r3,PACA_EXGEN+EX_DAR(r13)
lwz r4,PACA_EXGEN+EX_DSISR(r13)
std r3,_DAR(r1)
std r4,_DSISR(r1)
bl .save_nvgprs
addi r3,r1,STACK_FRAME_OVERHEAD
bl .machine_check_exception
b .ret_from_except
.align 7
.globl alignment_common
alignment_common:
......@@ -1263,6 +1343,120 @@ _GLOBAL(opal_mc_secondary_handler)
#endif /* CONFIG_PPC_POWERNV */
#define MACHINE_CHECK_HANDLER_WINDUP \
/* Clear MSR_RI before setting SRR0 and SRR1. */\
li r0,MSR_RI; \
mfmsr r9; /* get MSR value */ \
andc r9,r9,r0; \
mtmsrd r9,1; /* Clear MSR_RI */ \
/* Move original SRR0 and SRR1 into the respective regs */ \
ld r9,_MSR(r1); \
mtspr SPRN_SRR1,r9; \
ld r3,_NIP(r1); \
mtspr SPRN_SRR0,r3; \
ld r9,_CTR(r1); \
mtctr r9; \
ld r9,_XER(r1); \
mtxer r9; \
ld r9,_LINK(r1); \
mtlr r9; \
REST_GPR(0, r1); \
REST_8GPRS(2, r1); \
REST_GPR(10, r1); \
ld r11,_CCR(r1); \
mtcr r11; \
/* Decrement paca->in_mce. */ \
lhz r12,PACA_IN_MCE(r13); \
subi r12,r12,1; \
sth r12,PACA_IN_MCE(r13); \
REST_GPR(11, r1); \
REST_2GPRS(12, r1); \
/* restore original r1. */ \
ld r1,GPR1(r1)
/*
* Handle machine check early in real mode. We come here with
* ME=1, MMU (IR=0 and DR=0) off and using MC emergency stack.
*/
.align 7
.globl machine_check_handle_early
machine_check_handle_early:
std r0,GPR0(r1) /* Save r0 */
EXCEPTION_PROLOG_COMMON_3(0x200)
bl .save_nvgprs
addi r3,r1,STACK_FRAME_OVERHEAD
bl .machine_check_early
ld r12,_MSR(r1)
#ifdef CONFIG_PPC_P7_NAP
/*
* Check if thread was in power saving mode. We come here when any
* of the following is true:
* a. thread wasn't in power saving mode
* b. thread was in power saving mode with no state loss or
* supervisor state loss
*
* Go back to nap again if (b) is true.
*/
rlwinm. r11,r12,47-31,30,31 /* Was it in power saving mode? */
beq 4f /* No, it wasn;t */
/* Thread was in power saving mode. Go back to nap again. */
cmpwi r11,2
bne 3f
/* Supervisor state loss */
li r0,1
stb r0,PACA_NAPSTATELOST(r13)
3: bl .machine_check_queue_event
MACHINE_CHECK_HANDLER_WINDUP
GET_PACA(r13)
ld r1,PACAR1(r13)
b .power7_enter_nap_mode
4:
#endif
/*
* Check if we are coming from hypervisor userspace. If yes then we
* continue in host kernel in V mode to deliver the MC event.
*/
rldicl. r11,r12,4,63 /* See if MC hit while in HV mode. */
beq 5f
andi. r11,r12,MSR_PR /* See if coming from user. */
bne 9f /* continue in V mode if we are. */
5:
#ifdef CONFIG_KVM_BOOK3S_64_HV
/*
* We are coming from kernel context. Check if we are coming from
* guest. if yes, then we can continue. We will fall through
* do_kvm_200->kvmppc_interrupt to deliver the MC event to guest.
*/
lbz r11,HSTATE_IN_GUEST(r13)
cmpwi r11,0 /* Check if coming from guest */
bne 9f /* continue if we are. */
#endif
/*
* At this point we are not sure about what context we come from.
* Queue up the MCE event and return from the interrupt.
* But before that, check if this is an un-recoverable exception.
* If yes, then stay on emergency stack and panic.
*/
andi. r11,r12,MSR_RI
bne 2f
1: addi r3,r1,STACK_FRAME_OVERHEAD
bl .unrecoverable_exception
b 1b
2:
/*
* Return from MC interrupt.
* Queue up the MCE event so that we can log it later, while
* returning from kernel or opal call.
*/
bl .machine_check_queue_event
MACHINE_CHECK_HANDLER_WINDUP
rfid
9:
/* Deliver the machine check to host kernel in V mode. */
MACHINE_CHECK_HANDLER_WINDUP
b machine_check_pSeries
/*
* r13 points to the PACA, r9 contains the saved CR,
* r12 contain the saved SRR1, SRR0 is still ready for return
......
......@@ -80,6 +80,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
blr
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
/*
* Enable use of the FPU, and VSX if possible, for the caller.
*/
_GLOBAL(fp_enable)
mfmsr r3
ori r3,r3,MSR_FP
#ifdef CONFIG_VSX
BEGIN_FTR_SECTION
oris r3,r3,MSR_VSX@h
END_FTR_SECTION_IFSET(CPU_FTR_VSX)
#endif
SYNC
MTMSRD(r3)
isync /* (not necessary for arch 2.02 and later) */
blr
/*
* Load state from memory into FP registers including FPSCR.
* Assumes the caller has enabled FP in the MSR.
......
......@@ -176,6 +176,8 @@ skpinv: addi r6,r6,1 /* Increment */
/* 7. Jump to KERNELBASE mapping */
lis r6,(KERNELBASE & ~0xfff)@h
ori r6,r6,(KERNELBASE & ~0xfff)@l
rlwinm r7,r25,0,0x03ffffff
add r6,r7,r6
#elif defined(ENTRY_MAPPING_KEXEC_SETUP)
/*
......
......@@ -23,6 +23,7 @@
*/
#include <linux/threads.h>
#include <linux/init.h>
#include <asm/reg.h>
#include <asm/page.h>
#include <asm/mmu.h>
......
......@@ -65,29 +65,78 @@ _ENTRY(_start);
nop
/* Translate device tree address to physical, save in r30/r31 */
mfmsr r16
mfspr r17,SPRN_PID
rlwinm r17,r17,16,0x3fff0000 /* turn PID into MAS6[SPID] */
rlwimi r17,r16,28,0x00000001 /* turn MSR[DS] into MAS6[SAS] */
mtspr SPRN_MAS6,r17
tlbsx 0,r3 /* must succeed */
mfspr r16,SPRN_MAS1
mfspr r20,SPRN_MAS3
rlwinm r17,r16,25,0x1f /* r17 = log2(page size) */
li r18,1024
slw r18,r18,r17 /* r18 = page size */
addi r18,r18,-1
and r19,r3,r18 /* r19 = page offset */
andc r31,r20,r18 /* r31 = page base */
or r31,r31,r19 /* r31 = devtree phys addr */
mfspr r30,SPRN_MAS7
bl get_phys_addr
mr r30,r3
mr r31,r4
li r25,0 /* phys kernel start (low) */
li r24,0 /* CPU number */
li r23,0 /* phys kernel start (high) */
#ifdef CONFIG_RELOCATABLE
LOAD_REG_ADDR_PIC(r3, _stext) /* Get our current runtime base */
/* Translate _stext address to physical, save in r23/r25 */
bl get_phys_addr
mr r23,r3
mr r25,r4
bl 0f
0: mflr r8
addis r3,r8,(is_second_reloc - 0b)@ha
lwz r19,(is_second_reloc - 0b)@l(r3)
/* Check if this is the second relocation. */
cmpwi r19,1
bne 1f
/*
* For the second relocation, we already get the real memstart_addr
* from device tree. So we will map PAGE_OFFSET to memstart_addr,
* then the virtual address of start kernel should be:
* PAGE_OFFSET + (kernstart_addr - memstart_addr)
* Since the offset between kernstart_addr and memstart_addr should
* never be beyond 1G, so we can just use the lower 32bit of them
* for the calculation.
*/
lis r3,PAGE_OFFSET@h
addis r4,r8,(kernstart_addr - 0b)@ha
addi r4,r4,(kernstart_addr - 0b)@l
lwz r5,4(r4)
addis r6,r8,(memstart_addr - 0b)@ha
addi r6,r6,(memstart_addr - 0b)@l
lwz r7,4(r6)
subf r5,r7,r5
add r3,r3,r5
b 2f
1:
/*
* We have the runtime (virutal) address of our base.
* We calculate our shift of offset from a 64M page.
* We could map the 64M page we belong to at PAGE_OFFSET and
* get going from there.
*/
lis r4,KERNELBASE@h
ori r4,r4,KERNELBASE@l
rlwinm r6,r25,0,0x3ffffff /* r6 = PHYS_START % 64M */
rlwinm r5,r4,0,0x3ffffff /* r5 = KERNELBASE % 64M */
subf r3,r5,r6 /* r3 = r6 - r5 */
add r3,r4,r3 /* Required Virtual Address */
2: bl relocate
/*
* For the second relocation, we already set the right tlb entries
* for the kernel space, so skip the code in fsl_booke_entry_mapping.S
*/
cmpwi r19,1
beq set_ivor
#endif
/* We try to not make any assumptions about how the boot loader
* setup or used the TLBs. We invalidate all mappings from the
* boot loader and load a single entry in TLB1[0] to map the
......@@ -113,6 +162,7 @@ _ENTRY(__early_start)
#include "fsl_booke_entry_mapping.S"
#undef ENTRY_MAPPING_BOOT_SETUP
set_ivor:
/* Establish the interrupt vector offsets */
SET_IVOR(0, CriticalInput);
SET_IVOR(1, MachineCheck);
......@@ -166,8 +216,7 @@ _ENTRY(__early_start)
/* Check to see if we're the second processor, and jump
* to the secondary_start code if so
*/
lis r24, boot_cpuid@h
ori r24, r24, boot_cpuid@l
LOAD_REG_ADDR_PIC(r24, boot_cpuid)
lwz r24, 0(r24)
cmpwi r24, -1
mfspr r24,SPRN_PIR
......@@ -197,6 +246,18 @@ _ENTRY(__early_start)
bl early_init
#ifdef CONFIG_RELOCATABLE
mr r3,r30
mr r4,r31
#ifdef CONFIG_PHYS_64BIT
mr r5,r23
mr r6,r25
#else
mr r5,r25
#endif
bl relocate_init
#endif
#ifdef CONFIG_DYNAMIC_MEMSTART
lis r3,kernstart_addr@ha
la r3,kernstart_addr@l(r3)
......@@ -855,6 +916,33 @@ KernelSPE:
#endif /* CONFIG_SPE */
/*
* Translate the effec addr in r3 to phys addr. The phys addr will be put
* into r3(higher 32bit) and r4(lower 32bit)
*/
get_phys_addr:
mfmsr r8
mfspr r9,SPRN_PID
rlwinm r9,r9,16,0x3fff0000 /* turn PID into MAS6[SPID] */
rlwimi r9,r8,28,0x00000001 /* turn MSR[DS] into MAS6[SAS] */
mtspr SPRN_MAS6,r9
tlbsx 0,r3 /* must succeed */
mfspr r8,SPRN_MAS1
mfspr r12,SPRN_MAS3
rlwinm r9,r8,25,0x1f /* r9 = log2(page size) */
li r10,1024
slw r10,r10,r9 /* r10 = page size */
addi r10,r10,-1
and r11,r3,r10 /* r11 = page offset */
andc r4,r12,r10 /* r4 = page base */
or r4,r4,r11 /* r4 = devtree phys addr */
#ifdef CONFIG_PHYS_64BIT
mfspr r3,SPRN_MAS7
#endif
blr
/*
* Global functions
*/
......@@ -1057,24 +1145,36 @@ _GLOBAL(__flush_disable_L1)
/* When we get here, r24 needs to hold the CPU # */
.globl __secondary_start
__secondary_start:
lis r3,__secondary_hold_acknowledge@h
ori r3,r3,__secondary_hold_acknowledge@l
stw r24,0(r3)
li r3,0
mr r4,r24 /* Why? */
bl call_setup_cpu
lis r3,tlbcam_index@ha
lwz r3,tlbcam_index@l(r3)
LOAD_REG_ADDR_PIC(r3, tlbcam_index)
lwz r3,0(r3)
mtctr r3
li r26,0 /* r26 safe? */
bl switch_to_as1
mr r27,r3 /* tlb entry */
/* Load each CAM entry */
1: mr r3,r26
bl loadcam_entry
addi r26,r26,1
bdnz 1b
mr r3,r27 /* tlb entry */
LOAD_REG_ADDR_PIC(r4, memstart_addr)
lwz r4,0(r4)
mr r5,r25 /* phys kernel start */
rlwinm r5,r5,0,~0x3ffffff /* aligned 64M */
subf r4,r5,r4 /* memstart_addr - phys kernel start */
li r5,0 /* no device tree */
li r6,0 /* not boot cpu */
bl restore_to_as0
lis r3,__secondary_hold_acknowledge@h
ori r3,r3,__secondary_hold_acknowledge@l
stw r24,0(r3)
li r3,0
mr r4,r24 /* Why? */
bl call_setup_cpu
/* get current_thread_info and current */
lis r1,secondary_ti@ha
......@@ -1110,6 +1210,112 @@ __secondary_hold_acknowledge:
.long -1
#endif
/*
* Create a tlb entry with the same effective and physical address as
* the tlb entry used by the current running code. But set the TS to 1.
* Then switch to the address space 1. It will return with the r3 set to
* the ESEL of the new created tlb.
*/
_GLOBAL(switch_to_as1)
mflr r5
/* Find a entry not used */
mfspr r3,SPRN_TLB1CFG
andi. r3,r3,0xfff
mfspr r4,SPRN_PID
rlwinm r4,r4,16,0x3fff0000 /* turn PID into MAS6[SPID] */
mtspr SPRN_MAS6,r4
1: lis r4,0x1000 /* Set MAS0(TLBSEL) = 1 */
addi r3,r3,-1
rlwimi r4,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
mtspr SPRN_MAS0,r4
tlbre
mfspr r4,SPRN_MAS1
andis. r4,r4,MAS1_VALID@h
bne 1b
/* Get the tlb entry used by the current running code */
bl 0f
0: mflr r4
tlbsx 0,r4
mfspr r4,SPRN_MAS1
ori r4,r4,MAS1_TS /* Set the TS = 1 */
mtspr SPRN_MAS1,r4
mfspr r4,SPRN_MAS0
rlwinm r4,r4,0,~MAS0_ESEL_MASK
rlwimi r4,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
mtspr SPRN_MAS0,r4
tlbwe
isync
sync
mfmsr r4
ori r4,r4,MSR_IS | MSR_DS
mtspr SPRN_SRR0,r5
mtspr SPRN_SRR1,r4
sync
rfi
/*
* Restore to the address space 0 and also invalidate the tlb entry created
* by switch_to_as1.
* r3 - the tlb entry which should be invalidated
* r4 - __pa(PAGE_OFFSET in AS1) - __pa(PAGE_OFFSET in AS0)
* r5 - device tree virtual address. If r4 is 0, r5 is ignored.
* r6 - boot cpu
*/
_GLOBAL(restore_to_as0)
mflr r0
bl 0f
0: mflr r9
addi r9,r9,1f - 0b
/*
* We may map the PAGE_OFFSET in AS0 to a different physical address,
* so we need calculate the right jump and device tree address based
* on the offset passed by r4.
*/
add r9,r9,r4
add r5,r5,r4
add r0,r0,r4
2: mfmsr r7
li r8,(MSR_IS | MSR_DS)
andc r7,r7,r8
mtspr SPRN_SRR0,r9
mtspr SPRN_SRR1,r7
sync
rfi
/* Invalidate the temporary tlb entry for AS1 */
1: lis r9,0x1000 /* Set MAS0(TLBSEL) = 1 */
rlwimi r9,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
mtspr SPRN_MAS0,r9
tlbre
mfspr r9,SPRN_MAS1
rlwinm r9,r9,0,2,31 /* Clear MAS1 Valid and IPPROT */
mtspr SPRN_MAS1,r9
tlbwe
isync
cmpwi r4,0
cmpwi cr1,r6,0
cror eq,4*cr1+eq,eq
bne 3f /* offset != 0 && is_boot_cpu */
mtlr r0
blr
/*
* The PAGE_OFFSET will map to a different physical address,
* jump to _start to do another relocation again.
*/
3: mr r3,r5
bl _start
/*
* We put a few things here that have to be page-aligned. This stuff
* goes at the beginning of the data segment, which is page-aligned.
......
......@@ -28,7 +28,6 @@
#include <linux/percpu.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/smp.h>
#include <asm/hw_breakpoint.h>
......
......@@ -84,6 +84,7 @@ _GLOBAL(power7_nap)
std r9,_MSR(r1)
std r1,PACAR1(r13)
_GLOBAL(power7_enter_nap_mode)
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
/* Tell KVM we're napping */
li r4,KVM_HWTHREAD_IN_NAP
......
......@@ -3,7 +3,6 @@
*
* (C) Copyright 2004 Linus Torvalds
*/
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/mm.h>
#include <linux/export.h>
......
......@@ -251,14 +251,13 @@ static unsigned long iommu_range_alloc(struct device *dev,
if (dev)
boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
1 << IOMMU_PAGE_SHIFT);
1 << tbl->it_page_shift);
else
boundary_size = ALIGN(1UL << 32, 1 << IOMMU_PAGE_SHIFT);
boundary_size = ALIGN(1UL << 32, 1 << tbl->it_page_shift);
/* 4GB boundary for iseries_hv_alloc and iseries_hv_map */
n = iommu_area_alloc(tbl->it_map, limit, start, npages,
tbl->it_offset, boundary_size >> IOMMU_PAGE_SHIFT,
align_mask);
n = iommu_area_alloc(tbl->it_map, limit, start, npages, tbl->it_offset,
boundary_size >> tbl->it_page_shift, align_mask);
if (n == -1) {
if (likely(pass == 0)) {
/* First try the pool from the start */
......@@ -320,12 +319,12 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
return DMA_ERROR_CODE;
entry += tbl->it_offset; /* Offset into real TCE table */
ret = entry << IOMMU_PAGE_SHIFT; /* Set the return dma address */
ret = entry << tbl->it_page_shift; /* Set the return dma address */
/* Put the TCEs in the HW table */
build_fail = ppc_md.tce_build(tbl, entry, npages,
(unsigned long)page & IOMMU_PAGE_MASK,
direction, attrs);
(unsigned long)page &
IOMMU_PAGE_MASK(tbl), direction, attrs);
/* ppc_md.tce_build() only returns non-zero for transient errors.
* Clean up the table bitmap in this case and return
......@@ -352,7 +351,7 @@ static bool iommu_free_check(struct iommu_table *tbl, dma_addr_t dma_addr,
{
unsigned long entry, free_entry;
entry = dma_addr >> IOMMU_PAGE_SHIFT;
entry = dma_addr >> tbl->it_page_shift;
free_entry = entry - tbl->it_offset;
if (((free_entry + npages) > tbl->it_size) ||
......@@ -401,7 +400,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
unsigned long flags;
struct iommu_pool *pool;
entry = dma_addr >> IOMMU_PAGE_SHIFT;
entry = dma_addr >> tbl->it_page_shift;
free_entry = entry - tbl->it_offset;
pool = get_pool(tbl, free_entry);
......@@ -468,13 +467,13 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
}
/* Allocate iommu entries for that segment */
vaddr = (unsigned long) sg_virt(s);
npages = iommu_num_pages(vaddr, slen, IOMMU_PAGE_SIZE);
npages = iommu_num_pages(vaddr, slen, IOMMU_PAGE_SIZE(tbl));
align = 0;
if (IOMMU_PAGE_SHIFT < PAGE_SHIFT && slen >= PAGE_SIZE &&
if (tbl->it_page_shift < PAGE_SHIFT && slen >= PAGE_SIZE &&
(vaddr & ~PAGE_MASK) == 0)
align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
align = PAGE_SHIFT - tbl->it_page_shift;
entry = iommu_range_alloc(dev, tbl, npages, &handle,
mask >> IOMMU_PAGE_SHIFT, align);
mask >> tbl->it_page_shift, align);
DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen);
......@@ -489,16 +488,16 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
/* Convert entry to a dma_addr_t */
entry += tbl->it_offset;
dma_addr = entry << IOMMU_PAGE_SHIFT;
dma_addr |= (s->offset & ~IOMMU_PAGE_MASK);
dma_addr = entry << tbl->it_page_shift;
dma_addr |= (s->offset & ~IOMMU_PAGE_MASK(tbl));
DBG(" - %lu pages, entry: %lx, dma_addr: %lx\n",
npages, entry, dma_addr);
/* Insert into HW table */
build_fail = ppc_md.tce_build(tbl, entry, npages,
vaddr & IOMMU_PAGE_MASK,
direction, attrs);
vaddr & IOMMU_PAGE_MASK(tbl),
direction, attrs);
if(unlikely(build_fail))
goto failure;
......@@ -559,9 +558,9 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
if (s->dma_length != 0) {
unsigned long vaddr, npages;
vaddr = s->dma_address & IOMMU_PAGE_MASK;
vaddr = s->dma_address & IOMMU_PAGE_MASK(tbl);
npages = iommu_num_pages(s->dma_address, s->dma_length,
IOMMU_PAGE_SIZE);
IOMMU_PAGE_SIZE(tbl));
__iommu_free(tbl, vaddr, npages);
s->dma_address = DMA_ERROR_CODE;
s->dma_length = 0;
......@@ -592,7 +591,7 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
if (sg->dma_length == 0)
break;
npages = iommu_num_pages(dma_handle, sg->dma_length,
IOMMU_PAGE_SIZE);
IOMMU_PAGE_SIZE(tbl));
__iommu_free(tbl, dma_handle, npages);
sg = sg_next(sg);
}
......@@ -676,7 +675,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
set_bit(0, tbl->it_map);
/* We only split the IOMMU table if we have 1GB or more of space */
if ((tbl->it_size << IOMMU_PAGE_SHIFT) >= (1UL * 1024 * 1024 * 1024))
if ((tbl->it_size << tbl->it_page_shift) >= (1UL * 1024 * 1024 * 1024))
tbl->nr_pools = IOMMU_NR_POOLS;
else
tbl->nr_pools = 1;
......@@ -768,16 +767,16 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,
vaddr = page_address(page) + offset;
uaddr = (unsigned long)vaddr;
npages = iommu_num_pages(uaddr, size, IOMMU_PAGE_SIZE);
npages = iommu_num_pages(uaddr, size, IOMMU_PAGE_SIZE(tbl));
if (tbl) {
align = 0;
if (IOMMU_PAGE_SHIFT < PAGE_SHIFT && size >= PAGE_SIZE &&
if (tbl->it_page_shift < PAGE_SHIFT && size >= PAGE_SIZE &&
((unsigned long)vaddr & ~PAGE_MASK) == 0)
align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
align = PAGE_SHIFT - tbl->it_page_shift;
dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction,
mask >> IOMMU_PAGE_SHIFT, align,
mask >> tbl->it_page_shift, align,
attrs);
if (dma_handle == DMA_ERROR_CODE) {
if (printk_ratelimit()) {
......@@ -786,7 +785,7 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,
npages);
}
} else
dma_handle |= (uaddr & ~IOMMU_PAGE_MASK);
dma_handle |= (uaddr & ~IOMMU_PAGE_MASK(tbl));
}
return dma_handle;
......@@ -801,7 +800,8 @@ void iommu_unmap_page(struct iommu_table *tbl, dma_addr_t dma_handle,
BUG_ON(direction == DMA_NONE);
if (tbl) {
npages = iommu_num_pages(dma_handle, size, IOMMU_PAGE_SIZE);
npages = iommu_num_pages(dma_handle, size,
IOMMU_PAGE_SIZE(tbl));
iommu_free(tbl, dma_handle, npages);
}
}
......@@ -845,10 +845,10 @@ void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
memset(ret, 0, size);
/* Set up tces to cover the allocated range */
nio_pages = size >> IOMMU_PAGE_SHIFT;
io_order = get_iommu_order(size);
nio_pages = size >> tbl->it_page_shift;
io_order = get_iommu_order(size, tbl);
mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
mask >> IOMMU_PAGE_SHIFT, io_order, NULL);
mask >> tbl->it_page_shift, io_order, NULL);
if (mapping == DMA_ERROR_CODE) {
free_pages((unsigned long)ret, order);
return NULL;
......@@ -864,7 +864,7 @@ void iommu_free_coherent(struct iommu_table *tbl, size_t size,
unsigned int nio_pages;
size = PAGE_ALIGN(size);
nio_pages = size >> IOMMU_PAGE_SHIFT;
nio_pages = size >> tbl->it_page_shift;
iommu_free(tbl, dma_handle, nio_pages);
size = PAGE_ALIGN(size);
free_pages((unsigned long)vaddr, get_order(size));
......@@ -935,10 +935,10 @@ int iommu_tce_clear_param_check(struct iommu_table *tbl,
if (tce_value)
return -EINVAL;
if (ioba & ~IOMMU_PAGE_MASK)
if (ioba & ~IOMMU_PAGE_MASK(tbl))
return -EINVAL;
ioba >>= IOMMU_PAGE_SHIFT;
ioba >>= tbl->it_page_shift;
if (ioba < tbl->it_offset)
return -EINVAL;
......@@ -955,13 +955,13 @@ int iommu_tce_put_param_check(struct iommu_table *tbl,
if (!(tce & (TCE_PCI_WRITE | TCE_PCI_READ)))
return -EINVAL;
if (tce & ~(IOMMU_PAGE_MASK | TCE_PCI_WRITE | TCE_PCI_READ))
if (tce & ~(IOMMU_PAGE_MASK(tbl) | TCE_PCI_WRITE | TCE_PCI_READ))
return -EINVAL;
if (ioba & ~IOMMU_PAGE_MASK)
if (ioba & ~IOMMU_PAGE_MASK(tbl))
return -EINVAL;
ioba >>= IOMMU_PAGE_SHIFT;
ioba >>= tbl->it_page_shift;
if (ioba < tbl->it_offset)
return -EINVAL;
......@@ -1037,7 +1037,7 @@ int iommu_tce_build(struct iommu_table *tbl, unsigned long entry,
/* if (unlikely(ret))
pr_err("iommu_tce: %s failed on hwaddr=%lx ioba=%lx kva=%lx ret=%d\n",
__func__, hwaddr, entry << IOMMU_PAGE_SHIFT,
__func__, hwaddr, entry << IOMMU_PAGE_SHIFT(tbl),
hwaddr, ret); */
return ret;
......@@ -1049,14 +1049,14 @@ int iommu_put_tce_user_mode(struct iommu_table *tbl, unsigned long entry,
{
int ret;
struct page *page = NULL;
unsigned long hwaddr, offset = tce & IOMMU_PAGE_MASK & ~PAGE_MASK;
unsigned long hwaddr, offset = tce & IOMMU_PAGE_MASK(tbl) & ~PAGE_MASK;
enum dma_data_direction direction = iommu_tce_direction(tce);
ret = get_user_pages_fast(tce & PAGE_MASK, 1,
direction != DMA_TO_DEVICE, &page);
if (unlikely(ret != 1)) {
/* pr_err("iommu_tce: get_user_pages_fast failed tce=%lx ioba=%lx ret=%d\n",
tce, entry << IOMMU_PAGE_SHIFT, ret); */
tce, entry << IOMMU_PAGE_SHIFT(tbl), ret); */
return -EFAULT;
}
hwaddr = (unsigned long) page_address(page) + offset;
......@@ -1067,7 +1067,7 @@ int iommu_put_tce_user_mode(struct iommu_table *tbl, unsigned long entry,
if (ret < 0)
pr_err("iommu_tce: %s failed ioba=%lx, tce=%lx, ret=%d\n",
__func__, entry << IOMMU_PAGE_SHIFT, tce, ret);
__func__, entry << tbl->it_page_shift, tce, ret);
return ret;
}
......@@ -1105,7 +1105,7 @@ void iommu_release_ownership(struct iommu_table *tbl)
}
EXPORT_SYMBOL_GPL(iommu_release_ownership);
static int iommu_add_device(struct device *dev)
int iommu_add_device(struct device *dev)
{
struct iommu_table *tbl;
int ret = 0;
......@@ -1127,6 +1127,12 @@ static int iommu_add_device(struct device *dev)
pr_debug("iommu_tce: adding %s to iommu group %d\n",
dev_name(dev), iommu_group_id(tbl->it_group));
if (PAGE_SIZE < IOMMU_PAGE_SIZE(tbl)) {
pr_err("iommu_tce: unsupported iommu page size.");
pr_err("%s has not been added\n", dev_name(dev));
return -EINVAL;
}
ret = iommu_group_add_device(tbl->it_group, dev);
if (ret < 0)
pr_err("iommu_tce: %s has not been added, ret=%d\n",
......@@ -1134,52 +1140,23 @@ static int iommu_add_device(struct device *dev)
return ret;
}
EXPORT_SYMBOL_GPL(iommu_add_device);
static void iommu_del_device(struct device *dev)
{
iommu_group_remove_device(dev);
}
static int iommu_bus_notifier(struct notifier_block *nb,
unsigned long action, void *data)
void iommu_del_device(struct device *dev)
{
struct device *dev = data;
switch (action) {
case BUS_NOTIFY_ADD_DEVICE:
return iommu_add_device(dev);
case BUS_NOTIFY_DEL_DEVICE:
iommu_del_device(dev);
return 0;
default:
return 0;
/*
* Some devices might not have IOMMU table and group
* and we needn't detach them from the associated
* IOMMU groups
*/
if (!dev->iommu_group) {
pr_debug("iommu_tce: skipping device %s with no tbl\n",
dev_name(dev));
return;
}
}
static struct notifier_block tce_iommu_bus_nb = {
.notifier_call = iommu_bus_notifier,
};
static int __init tce_iommu_init(void)
{
struct pci_dev *pdev = NULL;
BUILD_BUG_ON(PAGE_SIZE < IOMMU_PAGE_SIZE);
for_each_pci_dev(pdev)
iommu_add_device(&pdev->dev);
bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb);
return 0;
}
subsys_initcall_sync(tce_iommu_init);
#else
void iommu_register_group(struct iommu_table *tbl,
int pci_domain_number, unsigned long pe_num)
{
iommu_group_remove_device(dev);
}
EXPORT_SYMBOL_GPL(iommu_del_device);
#endif /* CONFIG_IOMMU_API */
......@@ -354,8 +354,13 @@ int arch_show_interrupts(struct seq_file *p, int prec)
seq_printf(p, "%*s: ", prec, "LOC");
for_each_online_cpu(j)
seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs);
seq_printf(p, " Local timer interrupts\n");
seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs_event);
seq_printf(p, " Local timer interrupts for timer event device\n");
seq_printf(p, "%*s: ", prec, "LOC");
for_each_online_cpu(j)
seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs_others);
seq_printf(p, " Local timer interrupts for others\n");
seq_printf(p, "%*s: ", prec, "SPU");
for_each_online_cpu(j)
......@@ -389,11 +394,12 @@ int arch_show_interrupts(struct seq_file *p, int prec)
*/
u64 arch_irq_stat_cpu(unsigned int cpu)
{
u64 sum = per_cpu(irq_stat, cpu).timer_irqs;
u64 sum = per_cpu(irq_stat, cpu).timer_irqs_event;
sum += per_cpu(irq_stat, cpu).pmu_irqs;
sum += per_cpu(irq_stat, cpu).mce_exceptions;
sum += per_cpu(irq_stat, cpu).spurious_irqs;
sum += per_cpu(irq_stat, cpu).timer_irqs_others;
#ifdef CONFIG_PPC_DOORBELL
sum += per_cpu(irq_stat, cpu).doorbell_irqs;
#endif
......
......@@ -15,7 +15,6 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/kgdb.h>
#include <linux/smp.h>
#include <linux/signal.h>
......
/*
* Machine check exception handling.
*
* 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.
*
* Copyright 2013 IBM Corporation
* Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
*/
#undef DEBUG
#define pr_fmt(fmt) "mce: " fmt
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/percpu.h>
#include <linux/export.h>
#include <linux/irq_work.h>
#include <asm/mce.h>
static DEFINE_PER_CPU(int, mce_nest_count);
static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event);
/* Queue for delayed MCE events. */
static DEFINE_PER_CPU(int, mce_queue_count);
static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event_queue);
static void machine_check_process_queued_event(struct irq_work *work);
struct irq_work mce_event_process_work = {
.func = machine_check_process_queued_event,
};
static void mce_set_error_info(struct machine_check_event *mce,
struct mce_error_info *mce_err)
{
mce->error_type = mce_err->error_type;
switch (mce_err->error_type) {
case MCE_ERROR_TYPE_UE:
mce->u.ue_error.ue_error_type = mce_err->u.ue_error_type;
break;
case MCE_ERROR_TYPE_SLB:
mce->u.slb_error.slb_error_type = mce_err->u.slb_error_type;
break;
case MCE_ERROR_TYPE_ERAT:
mce->u.erat_error.erat_error_type = mce_err->u.erat_error_type;
break;
case MCE_ERROR_TYPE_TLB:
mce->u.tlb_error.tlb_error_type = mce_err->u.tlb_error_type;
break;
case MCE_ERROR_TYPE_UNKNOWN:
default:
break;
}
}
/*
* Decode and save high level MCE information into per cpu buffer which
* is an array of machine_check_event structure.
*/
void save_mce_event(struct pt_regs *regs, long handled,
struct mce_error_info *mce_err,
uint64_t addr)
{
uint64_t srr1;
int index = __get_cpu_var(mce_nest_count)++;
struct machine_check_event *mce = &__get_cpu_var(mce_event[index]);
/*
* Return if we don't have enough space to log mce event.
* mce_nest_count may go beyond MAX_MC_EVT but that's ok,
* the check below will stop buffer overrun.
*/
if (index >= MAX_MC_EVT)
return;
/* Populate generic machine check info */
mce->version = MCE_V1;
mce->srr0 = regs->nip;
mce->srr1 = regs->msr;
mce->gpr3 = regs->gpr[3];
mce->in_use = 1;
mce->initiator = MCE_INITIATOR_CPU;
if (handled)
mce->disposition = MCE_DISPOSITION_RECOVERED;
else
mce->disposition = MCE_DISPOSITION_NOT_RECOVERED;
mce->severity = MCE_SEV_ERROR_SYNC;
srr1 = regs->msr;
/*
* Populate the mce error_type and type-specific error_type.
*/
mce_set_error_info(mce, mce_err);
if (!addr)
return;
if (mce->error_type == MCE_ERROR_TYPE_TLB) {
mce->u.tlb_error.effective_address_provided = true;
mce->u.tlb_error.effective_address = addr;
} else if (mce->error_type == MCE_ERROR_TYPE_SLB) {
mce->u.slb_error.effective_address_provided = true;
mce->u.slb_error.effective_address = addr;
} else if (mce->error_type == MCE_ERROR_TYPE_ERAT) {
mce->u.erat_error.effective_address_provided = true;
mce->u.erat_error.effective_address = addr;
} else if (mce->error_type == MCE_ERROR_TYPE_UE) {
mce->u.ue_error.effective_address_provided = true;
mce->u.ue_error.effective_address = addr;
}
return;
}
/*
* get_mce_event:
* mce Pointer to machine_check_event structure to be filled.
* release Flag to indicate whether to free the event slot or not.
* 0 <= do not release the mce event. Caller will invoke
* release_mce_event() once event has been consumed.
* 1 <= release the slot.
*
* return 1 = success
* 0 = failure
*
* get_mce_event() will be called by platform specific machine check
* handle routine and in KVM.
* When we call get_mce_event(), we are still in interrupt context and
* preemption will not be scheduled until ret_from_expect() routine
* is called.
*/
int get_mce_event(struct machine_check_event *mce, bool release)
{
int index = __get_cpu_var(mce_nest_count) - 1;
struct machine_check_event *mc_evt;
int ret = 0;
/* Sanity check */
if (index < 0)
return ret;
/* Check if we have MCE info to process. */
if (index < MAX_MC_EVT) {
mc_evt = &__get_cpu_var(mce_event[index]);
/* Copy the event structure and release the original */
if (mce)
*mce = *mc_evt;
if (release)
mc_evt->in_use = 0;
ret = 1;
}
/* Decrement the count to free the slot. */
if (release)
__get_cpu_var(mce_nest_count)--;
return ret;
}
void release_mce_event(void)
{
get_mce_event(NULL, true);
}
/*
* Queue up the MCE event which then can be handled later.
*/
void machine_check_queue_event(void)
{
int index;
struct machine_check_event evt;
if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
return;
index = __get_cpu_var(mce_queue_count)++;
/* If queue is full, just return for now. */
if (index >= MAX_MC_EVT) {
__get_cpu_var(mce_queue_count)--;
return;
}
__get_cpu_var(mce_event_queue[index]) = evt;
/* Queue irq work to process this event later. */
irq_work_queue(&mce_event_process_work);
}
/*
* process pending MCE event from the mce event queue. This function will be
* called during syscall exit.
*/
static void machine_check_process_queued_event(struct irq_work *work)
{
int index;
/*
* For now just print it to console.
* TODO: log this error event to FSP or nvram.
*/
while (__get_cpu_var(mce_queue_count) > 0) {
index = __get_cpu_var(mce_queue_count) - 1;
machine_check_print_event_info(
&__get_cpu_var(mce_event_queue[index]));
__get_cpu_var(mce_queue_count)--;
}
}
void machine_check_print_event_info(struct machine_check_event *evt)
{
const char *level, *sevstr, *subtype;
static const char *mc_ue_types[] = {
"Indeterminate",
"Instruction fetch",
"Page table walk ifetch",
"Load/Store",
"Page table walk Load/Store",
};
static const char *mc_slb_types[] = {
"Indeterminate",
"Parity",
"Multihit",
};
static const char *mc_erat_types[] = {
"Indeterminate",
"Parity",
"Multihit",
};
static const char *mc_tlb_types[] = {
"Indeterminate",
"Parity",
"Multihit",
};
/* Print things out */
if (evt->version != MCE_V1) {
pr_err("Machine Check Exception, Unknown event version %d !\n",
evt->version);
return;
}
switch (evt->severity) {
case MCE_SEV_NO_ERROR:
level = KERN_INFO;
sevstr = "Harmless";
break;
case MCE_SEV_WARNING:
level = KERN_WARNING;
sevstr = "";
break;
case MCE_SEV_ERROR_SYNC:
level = KERN_ERR;
sevstr = "Severe";
break;
case MCE_SEV_FATAL:
default:
level = KERN_ERR;
sevstr = "Fatal";
break;
}
printk("%s%s Machine check interrupt [%s]\n", level, sevstr,
evt->disposition == MCE_DISPOSITION_RECOVERED ?
"Recovered" : "[Not recovered");
printk("%s Initiator: %s\n", level,
evt->initiator == MCE_INITIATOR_CPU ? "CPU" : "Unknown");
switch (evt->error_type) {
case MCE_ERROR_TYPE_UE:
subtype = evt->u.ue_error.ue_error_type <
ARRAY_SIZE(mc_ue_types) ?
mc_ue_types[evt->u.ue_error.ue_error_type]
: "Unknown";
printk("%s Error type: UE [%s]\n", level, subtype);
if (evt->u.ue_error.effective_address_provided)
printk("%s Effective address: %016llx\n",
level, evt->u.ue_error.effective_address);
if (evt->u.ue_error.physical_address_provided)
printk("%s Physial address: %016llx\n",
level, evt->u.ue_error.physical_address);
break;
case MCE_ERROR_TYPE_SLB:
subtype = evt->u.slb_error.slb_error_type <
ARRAY_SIZE(mc_slb_types) ?
mc_slb_types[evt->u.slb_error.slb_error_type]
: "Unknown";
printk("%s Error type: SLB [%s]\n", level, subtype);
if (evt->u.slb_error.effective_address_provided)
printk("%s Effective address: %016llx\n",
level, evt->u.slb_error.effective_address);
break;
case MCE_ERROR_TYPE_ERAT:
subtype = evt->u.erat_error.erat_error_type <
ARRAY_SIZE(mc_erat_types) ?
mc_erat_types[evt->u.erat_error.erat_error_type]
: "Unknown";
printk("%s Error type: ERAT [%s]\n", level, subtype);
if (evt->u.erat_error.effective_address_provided)
printk("%s Effective address: %016llx\n",
level, evt->u.erat_error.effective_address);
break;
case MCE_ERROR_TYPE_TLB:
subtype = evt->u.tlb_error.tlb_error_type <
ARRAY_SIZE(mc_tlb_types) ?
mc_tlb_types[evt->u.tlb_error.tlb_error_type]
: "Unknown";
printk("%s Error type: TLB [%s]\n", level, subtype);
if (evt->u.tlb_error.effective_address_provided)
printk("%s Effective address: %016llx\n",
level, evt->u.tlb_error.effective_address);
break;
default:
case MCE_ERROR_TYPE_UNKNOWN:
printk("%s Error type: Unknown\n", level);
break;
}
}
uint64_t get_mce_fault_addr(struct machine_check_event *evt)
{
switch (evt->error_type) {
case MCE_ERROR_TYPE_UE:
if (evt->u.ue_error.effective_address_provided)
return evt->u.ue_error.effective_address;
break;
case MCE_ERROR_TYPE_SLB:
if (evt->u.slb_error.effective_address_provided)
return evt->u.slb_error.effective_address;
break;
case MCE_ERROR_TYPE_ERAT:
if (evt->u.erat_error.effective_address_provided)
return evt->u.erat_error.effective_address;
break;
case MCE_ERROR_TYPE_TLB:
if (evt->u.tlb_error.effective_address_provided)
return evt->u.tlb_error.effective_address;
break;
default:
case MCE_ERROR_TYPE_UNKNOWN:
break;
}
return 0;
}
EXPORT_SYMBOL(get_mce_fault_addr);
/*
* Machine check exception handling CPU-side for power7 and power8
*
* 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.
*
* Copyright 2013 IBM Corporation
* Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
*/
#undef DEBUG
#define pr_fmt(fmt) "mce_power: " fmt
#include <linux/types.h>
#include <linux/ptrace.h>
#include <asm/mmu.h>
#include <asm/mce.h>
/* flush SLBs and reload */
static void flush_and_reload_slb(void)
{
struct slb_shadow *slb;
unsigned long i, n;
/* Invalidate all SLBs */
asm volatile("slbmte %0,%0; slbia" : : "r" (0));
#ifdef CONFIG_KVM_BOOK3S_HANDLER
/*
* If machine check is hit when in guest or in transition, we will
* only flush the SLBs and continue.
*/
if (get_paca()->kvm_hstate.in_guest)
return;
#endif
/* For host kernel, reload the SLBs from shadow SLB buffer. */
slb = get_slb_shadow();
if (!slb)
return;
n = min_t(u32, be32_to_cpu(slb->persistent), SLB_MIN_SIZE);
/* Load up the SLB entries from shadow SLB */
for (i = 0; i < n; i++) {
unsigned long rb = be64_to_cpu(slb->save_area[i].esid);
unsigned long rs = be64_to_cpu(slb->save_area[i].vsid);
rb = (rb & ~0xFFFul) | i;
asm volatile("slbmte %0,%1" : : "r" (rs), "r" (rb));
}
}
static long mce_handle_derror(uint64_t dsisr, uint64_t slb_error_bits)
{
long handled = 1;
/*
* flush and reload SLBs for SLB errors and flush TLBs for TLB errors.
* reset the error bits whenever we handle them so that at the end
* we can check whether we handled all of them or not.
* */
if (dsisr & slb_error_bits) {
flush_and_reload_slb();
/* reset error bits */
dsisr &= ~(slb_error_bits);
}
if (dsisr & P7_DSISR_MC_TLB_MULTIHIT_MFTLB) {
if (cur_cpu_spec && cur_cpu_spec->flush_tlb)
cur_cpu_spec->flush_tlb(TLBIEL_INVAL_PAGE);
/* reset error bits */
dsisr &= ~P7_DSISR_MC_TLB_MULTIHIT_MFTLB;
}
/* Any other errors we don't understand? */
if (dsisr & 0xffffffffUL)
handled = 0;
return handled;
}
static long mce_handle_derror_p7(uint64_t dsisr)
{
return mce_handle_derror(dsisr, P7_DSISR_MC_SLB_ERRORS);
}
static long mce_handle_common_ierror(uint64_t srr1)
{
long handled = 0;
switch (P7_SRR1_MC_IFETCH(srr1)) {
case 0:
break;
case P7_SRR1_MC_IFETCH_SLB_PARITY:
case P7_SRR1_MC_IFETCH_SLB_MULTIHIT:
/* flush and reload SLBs for SLB errors. */
flush_and_reload_slb();
handled = 1;
break;
case P7_SRR1_MC_IFETCH_TLB_MULTIHIT:
if (cur_cpu_spec && cur_cpu_spec->flush_tlb) {
cur_cpu_spec->flush_tlb(TLBIEL_INVAL_PAGE);
handled = 1;
}
break;
default:
break;
}
return handled;
}
static long mce_handle_ierror_p7(uint64_t srr1)
{
long handled = 0;
handled = mce_handle_common_ierror(srr1);
if (P7_SRR1_MC_IFETCH(srr1) == P7_SRR1_MC_IFETCH_SLB_BOTH) {
flush_and_reload_slb();
handled = 1;
}
return handled;
}
static void mce_get_common_ierror(struct mce_error_info *mce_err, uint64_t srr1)
{
switch (P7_SRR1_MC_IFETCH(srr1)) {
case P7_SRR1_MC_IFETCH_SLB_PARITY:
mce_err->error_type = MCE_ERROR_TYPE_SLB;
mce_err->u.slb_error_type = MCE_SLB_ERROR_PARITY;
break;
case P7_SRR1_MC_IFETCH_SLB_MULTIHIT:
mce_err->error_type = MCE_ERROR_TYPE_SLB;
mce_err->u.slb_error_type = MCE_SLB_ERROR_MULTIHIT;
break;
case P7_SRR1_MC_IFETCH_TLB_MULTIHIT:
mce_err->error_type = MCE_ERROR_TYPE_TLB;
mce_err->u.tlb_error_type = MCE_TLB_ERROR_MULTIHIT;
break;
case P7_SRR1_MC_IFETCH_UE:
case P7_SRR1_MC_IFETCH_UE_IFU_INTERNAL:
mce_err->error_type = MCE_ERROR_TYPE_UE;
mce_err->u.ue_error_type = MCE_UE_ERROR_IFETCH;
break;
case P7_SRR1_MC_IFETCH_UE_TLB_RELOAD:
mce_err->error_type = MCE_ERROR_TYPE_UE;
mce_err->u.ue_error_type =
MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH;
break;
}
}
static void mce_get_ierror_p7(struct mce_error_info *mce_err, uint64_t srr1)
{
mce_get_common_ierror(mce_err, srr1);
if (P7_SRR1_MC_IFETCH(srr1) == P7_SRR1_MC_IFETCH_SLB_BOTH) {
mce_err->error_type = MCE_ERROR_TYPE_SLB;
mce_err->u.slb_error_type = MCE_SLB_ERROR_INDETERMINATE;
}
}
static void mce_get_derror_p7(struct mce_error_info *mce_err, uint64_t dsisr)
{
if (dsisr & P7_DSISR_MC_UE) {
mce_err->error_type = MCE_ERROR_TYPE_UE;
mce_err->u.ue_error_type = MCE_UE_ERROR_LOAD_STORE;
} else if (dsisr & P7_DSISR_MC_UE_TABLEWALK) {
mce_err->error_type = MCE_ERROR_TYPE_UE;
mce_err->u.ue_error_type =
MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE;
} else if (dsisr & P7_DSISR_MC_ERAT_MULTIHIT) {
mce_err->error_type = MCE_ERROR_TYPE_ERAT;
mce_err->u.erat_error_type = MCE_ERAT_ERROR_MULTIHIT;
} else if (dsisr & P7_DSISR_MC_SLB_MULTIHIT) {
mce_err->error_type = MCE_ERROR_TYPE_SLB;
mce_err->u.slb_error_type = MCE_SLB_ERROR_MULTIHIT;
} else if (dsisr & P7_DSISR_MC_SLB_PARITY_MFSLB) {
mce_err->error_type = MCE_ERROR_TYPE_SLB;
mce_err->u.slb_error_type = MCE_SLB_ERROR_PARITY;
} else if (dsisr & P7_DSISR_MC_TLB_MULTIHIT_MFTLB) {
mce_err->error_type = MCE_ERROR_TYPE_TLB;
mce_err->u.tlb_error_type = MCE_TLB_ERROR_MULTIHIT;
} else if (dsisr & P7_DSISR_MC_SLB_MULTIHIT_PARITY) {
mce_err->error_type = MCE_ERROR_TYPE_SLB;
mce_err->u.slb_error_type = MCE_SLB_ERROR_INDETERMINATE;
}
}
long __machine_check_early_realmode_p7(struct pt_regs *regs)
{
uint64_t srr1, addr;
long handled = 1;
struct mce_error_info mce_error_info = { 0 };
srr1 = regs->msr;
/*
* Handle memory errors depending whether this was a load/store or
* ifetch exception. Also, populate the mce error_type and
* type-specific error_type from either SRR1 or DSISR, depending
* whether this was a load/store or ifetch exception
*/
if (P7_SRR1_MC_LOADSTORE(srr1)) {
handled = mce_handle_derror_p7(regs->dsisr);
mce_get_derror_p7(&mce_error_info, regs->dsisr);
addr = regs->dar;
} else {
handled = mce_handle_ierror_p7(srr1);
mce_get_ierror_p7(&mce_error_info, srr1);
addr = regs->nip;
}
save_mce_event(regs, handled, &mce_error_info, addr);
return handled;
}
static void mce_get_ierror_p8(struct mce_error_info *mce_err, uint64_t srr1)
{
mce_get_common_ierror(mce_err, srr1);
if (P7_SRR1_MC_IFETCH(srr1) == P8_SRR1_MC_IFETCH_ERAT_MULTIHIT) {
mce_err->error_type = MCE_ERROR_TYPE_ERAT;
mce_err->u.erat_error_type = MCE_ERAT_ERROR_MULTIHIT;
}
}
static void mce_get_derror_p8(struct mce_error_info *mce_err, uint64_t dsisr)
{
mce_get_derror_p7(mce_err, dsisr);
if (dsisr & P8_DSISR_MC_ERAT_MULTIHIT_SEC) {
mce_err->error_type = MCE_ERROR_TYPE_ERAT;
mce_err->u.erat_error_type = MCE_ERAT_ERROR_MULTIHIT;
}
}
static long mce_handle_ierror_p8(uint64_t srr1)
{
long handled = 0;
handled = mce_handle_common_ierror(srr1);
if (P7_SRR1_MC_IFETCH(srr1) == P8_SRR1_MC_IFETCH_ERAT_MULTIHIT) {
flush_and_reload_slb();
handled = 1;
}
return handled;
}
static long mce_handle_derror_p8(uint64_t dsisr)
{
return mce_handle_derror(dsisr, P8_DSISR_MC_SLB_ERRORS);
}
long __machine_check_early_realmode_p8(struct pt_regs *regs)
{
uint64_t srr1, addr;
long handled = 1;
struct mce_error_info mce_error_info = { 0 };
srr1 = regs->msr;
if (P7_SRR1_MC_LOADSTORE(srr1)) {
handled = mce_handle_derror_p8(regs->dsisr);
mce_get_derror_p8(&mce_error_info, regs->dsisr);
addr = regs->dar;
} else {
handled = mce_handle_ierror_p8(srr1);
mce_get_ierror_p8(&mce_error_info, srr1);
addr = regs->nip;
}
save_mce_event(regs, handled, &mce_error_info, addr);
return handled;
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册