mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 03:06:10 +00:00
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (151 commits) powerpc: Fix usage of 64-bit instruction in 32-bit altivec code MAINTAINERS: Add PowerPC patterns powerpc/pseries: Track previous CPPR values to correctly EOI interrupts powerpc/pseries: Correct pseries/dlpar.c build break without CONFIG_SMP powerpc: Make "intspec" pointers in irq_host->xlate() const powerpc/8xx: DTLB Miss cleanup powerpc/8xx: Remove DIRTY pte handling in DTLB Error. powerpc/8xx: Start using dcbX instructions in various copy routines powerpc/8xx: Restore _PAGE_WRITETHRU powerpc/8xx: Add missing Guarded setting in DTLB Error. powerpc/8xx: Fixup DAR from buggy dcbX instructions. powerpc/8xx: Tag DAR with 0x00f0 to catch buggy instructions. powerpc/8xx: Update TLB asm so it behaves as linux mm expects. powerpc/8xx: Invalidate non present TLBs powerpc/pseries: Serialize cpu hotplug operations during deactivate Vs deallocate pseries/pseries: Add code to online/offline CPUs of a DLPAR node powerpc: stop_this_cpu: remove the cpu from the online map. powerpc/pseries: Add kernel based CPU DLPAR handling sysfs/cpu: Add probe/release files powerpc/pseries: Kernel DLPAR Infrastructure ...
This commit is contained in:
commit
09cea96caa
234 changed files with 13150 additions and 2737 deletions
|
@ -62,6 +62,21 @@ Description: CPU topology files that describe kernel limits related to
|
|||
See Documentation/cputopology.txt for more information.
|
||||
|
||||
|
||||
What: /sys/devices/system/cpu/probe
|
||||
/sys/devices/system/cpu/release
|
||||
Date: November 2009
|
||||
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
|
||||
Description: Dynamic addition and removal of CPU's. This is not hotplug
|
||||
removal, this is meant complete removal/addition of the CPU
|
||||
from the system.
|
||||
|
||||
probe: writes to this file will dynamically add a CPU to the
|
||||
system. Information written to the file to add CPU's is
|
||||
architecture specific.
|
||||
|
||||
release: writes to this file dynamically remove a CPU from
|
||||
the system. Information writtento the file to remove CPU's
|
||||
is architecture specific.
|
||||
|
||||
What: /sys/devices/system/cpu/cpu#/node
|
||||
Date: October 2009
|
||||
|
|
|
@ -49,6 +49,12 @@ maxcpus=n Restrict boot time cpus to n. Say if you have 4 cpus, using
|
|||
additional_cpus=n (*) Use this to limit hotpluggable cpus. This option sets
|
||||
cpu_possible_map = cpu_present_map + additional_cpus
|
||||
|
||||
cede_offline={"off","on"} Use this option to disable/enable putting offlined
|
||||
processors to an extended H_CEDE state on
|
||||
supported pseries platforms.
|
||||
If nothing is specified,
|
||||
cede_offline is set to "on".
|
||||
|
||||
(*) Option valid only for following architectures
|
||||
- ia64
|
||||
|
||||
|
|
|
@ -20,12 +20,16 @@ Required properities:
|
|||
- compatible : should be "fsl,fpga-pixis".
|
||||
- reg : should contain the address and the length of the FPPGA register
|
||||
set.
|
||||
- interrupt-parent: should specify phandle for the interrupt controller.
|
||||
- interrupts : should specify event (wakeup) IRQ.
|
||||
|
||||
Example (MPC8610HPCD):
|
||||
|
||||
board-control@e8000000 {
|
||||
compatible = "fsl,fpga-pixis";
|
||||
reg = <0xe8000000 32>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <8 8>;
|
||||
};
|
||||
|
||||
* Freescale BCSR GPIO banks
|
||||
|
|
|
@ -103,7 +103,22 @@ fsl,mpc5200-gpt nodes
|
|||
---------------------
|
||||
On the mpc5200 and 5200b, GPT0 has a watchdog timer function. If the board
|
||||
design supports the internal wdt, then the device node for GPT0 should
|
||||
include the empty property 'fsl,has-wdt'.
|
||||
include the empty property 'fsl,has-wdt'. Note that this does not activate
|
||||
the watchdog. The timer will function as a GPT if the timer api is used, and
|
||||
it will function as watchdog if the watchdog device is used. The watchdog
|
||||
mode has priority over the gpt mode, i.e. if the watchdog is activated, any
|
||||
gpt api call to this timer will fail with -EBUSY.
|
||||
|
||||
If you add the property
|
||||
fsl,wdt-on-boot = <n>;
|
||||
GPT0 will be marked as in-use watchdog, i.e. blocking every gpt access to it.
|
||||
If n>0, the watchdog is started with a timeout of n seconds. If n=0, the
|
||||
configuration of the watchdog is not touched. This is useful in two cases:
|
||||
- just mark GPT0 as watchdog, blocking gpt accesses, and configure it later;
|
||||
- do not touch a configuration assigned by the boot loader which supervises
|
||||
the boot process itself.
|
||||
|
||||
The watchdog will respect the CONFIG_WATCHDOG_NOWAYOUT option.
|
||||
|
||||
An mpc5200-gpt can be used as a single line GPIO controller. To do so,
|
||||
add the following properties to the gpt node:
|
||||
|
|
15
MAINTAINERS
15
MAINTAINERS
|
@ -3260,6 +3260,7 @@ LINUX FOR IBM pSERIES (RS/6000)
|
|||
M: Paul Mackerras <paulus@au.ibm.com>
|
||||
W: http://www.ibm.com/linux/ltc/projects/ppc
|
||||
S: Supported
|
||||
F: arch/powerpc/boot/rs6000.h
|
||||
|
||||
LINUX FOR POWERPC (32-BIT AND 64-BIT)
|
||||
M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
|
||||
|
@ -3268,18 +3269,24 @@ W: http://www.penguinppc.org/
|
|||
L: linuxppc-dev@ozlabs.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git
|
||||
S: Supported
|
||||
F: Documentation/powerpc/
|
||||
F: arch/powerpc/
|
||||
|
||||
LINUX FOR POWER MACINTOSH
|
||||
M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
|
||||
W: http://www.penguinppc.org/
|
||||
L: linuxppc-dev@ozlabs.org
|
||||
S: Maintained
|
||||
F: arch/powerpc/platforms/powermac/
|
||||
F: drivers/macintosh/
|
||||
|
||||
LINUX FOR POWERPC EMBEDDED MPC5XXX
|
||||
M: Grant Likely <grant.likely@secretlab.ca>
|
||||
L: linuxppc-dev@ozlabs.org
|
||||
T: git git://git.secretlab.ca/git/linux-2.6.git
|
||||
S: Maintained
|
||||
F: arch/powerpc/platforms/512x/
|
||||
F: arch/powerpc/platforms/52xx/
|
||||
|
||||
LINUX FOR POWERPC EMBEDDED PPC4XX
|
||||
M: Josh Boyer <jwboyer@linux.vnet.ibm.com>
|
||||
|
@ -3288,6 +3295,8 @@ W: http://www.penguinppc.org/
|
|||
L: linuxppc-dev@ozlabs.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx.git
|
||||
S: Maintained
|
||||
F: arch/powerpc/platforms/40x/
|
||||
F: arch/powerpc/platforms/44x/
|
||||
|
||||
LINUX FOR POWERPC EMBEDDED XILINX VIRTEX
|
||||
M: Grant Likely <grant.likely@secretlab.ca>
|
||||
|
@ -3295,6 +3304,8 @@ W: http://wiki.secretlab.ca/index.php/Linux_on_Xilinx_Virtex
|
|||
L: linuxppc-dev@ozlabs.org
|
||||
T: git git://git.secretlab.ca/git/linux-2.6.git
|
||||
S: Maintained
|
||||
F: arch/powerpc/*/*virtex*
|
||||
F: arch/powerpc/*/*/*virtex*
|
||||
|
||||
LINUX FOR POWERPC EMBEDDED PPC8XX
|
||||
M: Vitaly Bordug <vitb@kernel.crashing.org>
|
||||
|
@ -3308,12 +3319,16 @@ M: Kumar Gala <galak@kernel.crashing.org>
|
|||
W: http://www.penguinppc.org/
|
||||
L: linuxppc-dev@ozlabs.org
|
||||
S: Maintained
|
||||
F: arch/powerpc/platforms/83xx/
|
||||
|
||||
LINUX FOR POWERPC PA SEMI PWRFICIENT
|
||||
M: Olof Johansson <olof@lixom.net>
|
||||
W: http://www.pasemi.com/
|
||||
L: linuxppc-dev@ozlabs.org
|
||||
S: Supported
|
||||
F: arch/powerpc/platforms/pasemi/
|
||||
F: drivers/*/*pasemi*
|
||||
F: drivers/*/*/*pasemi*
|
||||
|
||||
LINUX SECURITY MODULE (LSM) FRAMEWORK
|
||||
M: Chris Wright <chrisw@sous-sol.org>
|
||||
|
|
|
@ -56,6 +56,16 @@ config IRQ_PER_CPU
|
|||
bool
|
||||
default y
|
||||
|
||||
config NR_IRQS
|
||||
int "Number of virtual interrupt numbers"
|
||||
range 32 512
|
||||
default "512"
|
||||
help
|
||||
This defines the number of virtual interrupt numbers the kernel
|
||||
can manage. Virtual interrupt numbers are what you see in
|
||||
/proc/interrupts. If you configure your system to have too few,
|
||||
drivers will fail to load or worse - handle with care.
|
||||
|
||||
config STACKTRACE_SUPPORT
|
||||
bool
|
||||
default y
|
||||
|
@ -199,24 +209,14 @@ config DEFAULT_UIMAGE
|
|||
config REDBOOT
|
||||
bool
|
||||
|
||||
config HIBERNATE_32
|
||||
bool
|
||||
depends on (PPC_PMAC && !SMP) || BROKEN
|
||||
default y
|
||||
|
||||
config HIBERNATE_64
|
||||
bool
|
||||
depends on BROKEN || (PPC_PMAC64 && EXPERIMENTAL)
|
||||
default y
|
||||
|
||||
config ARCH_HIBERNATION_POSSIBLE
|
||||
bool
|
||||
depends on (PPC64 && HIBERNATE_64) || (PPC32 && HIBERNATE_32)
|
||||
default y
|
||||
|
||||
config ARCH_SUSPEND_POSSIBLE
|
||||
def_bool y
|
||||
depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx
|
||||
depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \
|
||||
PPC_85xx || PPC_86xx
|
||||
|
||||
config PPC_DCR_NATIVE
|
||||
bool
|
||||
|
@ -320,6 +320,10 @@ config HOTPLUG_CPU
|
|||
|
||||
Say N if you are unsure.
|
||||
|
||||
config ARCH_CPU_PROBE_RELEASE
|
||||
def_bool y
|
||||
depends on HOTPLUG_CPU
|
||||
|
||||
config ARCH_ENABLE_MEMORY_HOTPLUG
|
||||
def_bool y
|
||||
|
||||
|
@ -378,6 +382,19 @@ config IRQ_ALL_CPUS
|
|||
CPU. Generally saying Y is safe, although some problems have been
|
||||
reported with SMP Power Macintoshes with this option enabled.
|
||||
|
||||
config SPARSE_IRQ
|
||||
bool "Support sparse irq numbering"
|
||||
default y
|
||||
help
|
||||
This enables support for sparse irqs. This is useful for distro
|
||||
kernels that want to define a high CONFIG_NR_CPUS value but still
|
||||
want to have low kernel memory footprint on smaller machines.
|
||||
|
||||
( Sparse IRQs can also be beneficial on NUMA boxes, as they spread
|
||||
out the irq_desc[] array in a more NUMA-friendly way. )
|
||||
|
||||
If you don't know what to do here, say Y.
|
||||
|
||||
config NUMA
|
||||
bool "NUMA support"
|
||||
depends on PPC64
|
||||
|
@ -652,6 +669,14 @@ config FSL_PCI
|
|||
select PPC_INDIRECT_PCI
|
||||
select PCI_QUIRKS
|
||||
|
||||
config FSL_PMC
|
||||
bool
|
||||
default y
|
||||
depends on SUSPEND && (PPC_85xx || PPC_86xx)
|
||||
help
|
||||
Freescale MPC85xx/MPC86xx power management controller support
|
||||
(suspend/resume). For MPC83xx see platforms/83xx/suspend.c
|
||||
|
||||
config 4xx_SOC
|
||||
bool
|
||||
|
||||
|
|
|
@ -352,6 +352,7 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x00000000>;
|
||||
rgmii-device = <&RGMII0>;
|
||||
|
@ -381,6 +382,7 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x00000000>;
|
||||
rgmii-device = <&RGMII0>;
|
||||
|
|
|
@ -316,6 +316,7 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x00000000>;
|
||||
rgmii-device = <&RGMII0>;
|
||||
|
@ -345,6 +346,7 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x00000000>;
|
||||
rgmii-device = <&RGMII0>;
|
||||
|
@ -375,6 +377,8 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
tx-fifo-size-gige = <16384>; /* emac2&3 only */
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x00000000>;
|
||||
rgmii-device = <&RGMII1>;
|
||||
|
@ -403,6 +407,8 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
tx-fifo-size-gige = <16384>; /* emac2&3 only */
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x00000000>;
|
||||
rgmii-device = <&RGMII1>;
|
||||
|
|
|
@ -118,6 +118,12 @@
|
|||
};
|
||||
};
|
||||
|
||||
nvram@3,0 {
|
||||
device_type = "nvram";
|
||||
compatible = "simtek,stk14ca8";
|
||||
reg = <0x3 0x0 0x20000>;
|
||||
};
|
||||
|
||||
fpga@4,0 {
|
||||
compatible = "gef,ppc9a-fpga-regs";
|
||||
reg = <0x4 0x0 0x40>;
|
||||
|
|
|
@ -115,6 +115,12 @@
|
|||
};
|
||||
};
|
||||
|
||||
nvram@3,0 {
|
||||
device_type = "nvram";
|
||||
compatible = "simtek,stk14ca8";
|
||||
reg = <0x3 0x0 0x20000>;
|
||||
};
|
||||
|
||||
fpga@4,0 {
|
||||
compatible = "gef,fpga-regs";
|
||||
reg = <0x4 0x0 0x40>;
|
||||
|
|
|
@ -84,6 +84,12 @@
|
|||
6 0 0xfd000000 0x00800000 // IO FPGA (8-bit)
|
||||
7 0 0xfd800000 0x00800000>; // IO FPGA (32-bit)
|
||||
|
||||
nvram@3,0 {
|
||||
device_type = "nvram";
|
||||
compatible = "simtek,stk14ca8";
|
||||
reg = <0x3 0x0 0x20000>;
|
||||
};
|
||||
|
||||
fpga@4,0 {
|
||||
compatible = "gef,fpga-regs";
|
||||
reg = <0x4 0x0 0x40>;
|
||||
|
|
|
@ -292,6 +292,7 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x00000000>;
|
||||
rgmii-device = <&RGMII0>;
|
||||
|
@ -321,6 +322,7 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x00000000>;
|
||||
rgmii-device = <&RGMII0>;
|
||||
|
@ -351,6 +353,8 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
tx-fifo-size-gige = <16384>; /* emac2&3 only */
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x00000000>;
|
||||
rgmii-device = <&RGMII1>;
|
||||
|
@ -379,6 +383,8 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
tx-fifo-size-gige = <16384>; /* emac2&3 only */
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x00000000>;
|
||||
rgmii-device = <&RGMII1>;
|
||||
|
|
|
@ -226,6 +226,8 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
tx-fifo-size-gige = <16384>;
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x00000000>;
|
||||
rgmii-device = <&RGMII0>;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
/ {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
model = "amcc,katmai";
|
||||
compatible = "amcc,katmai";
|
||||
dcr-parent = <&{/cpus/cpu@0}>;
|
||||
|
@ -49,7 +49,7 @@
|
|||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x00000000 0x00000000>; /* Filled in by zImage */
|
||||
reg = <0x0 0x00000000 0x0 0x00000000>; /* Filled in by U-Boot */
|
||||
};
|
||||
|
||||
UIC0: interrupt-controller0 {
|
||||
|
@ -112,7 +112,15 @@
|
|||
compatible = "ibm,plb-440spe", "ibm,plb-440gp", "ibm,plb4";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
/* addr-child addr-parent size */
|
||||
ranges = <0x4 0xe0000000 0x4 0xe0000000 0x20000000
|
||||
0xc 0x00000000 0xc 0x00000000 0x20000000
|
||||
0xd 0x00000000 0xd 0x00000000 0x80000000
|
||||
0xd 0x80000000 0xd 0x80000000 0x80000000
|
||||
0xe 0x00000000 0xe 0x00000000 0x80000000
|
||||
0xe 0x80000000 0xe 0x80000000 0x80000000
|
||||
0xf 0x00000000 0xf 0x00000000 0x80000000
|
||||
0xf 0x80000000 0xf 0x80000000 0x80000000>;
|
||||
clock-frequency = <0>; /* Filled in by zImage */
|
||||
|
||||
SDRAM0: sdram {
|
||||
|
@ -245,8 +253,8 @@
|
|||
ranges = <0x02000000 0x00000000 0x80000000 0x0000000d 0x80000000 0x00000000 0x80000000
|
||||
0x01000000 0x00000000 0x00000000 0x0000000c 0x08000000 0x00000000 0x00010000>;
|
||||
|
||||
/* Inbound 2GB range starting at 0 */
|
||||
dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
|
||||
/* Inbound 4GB range starting at 0 */
|
||||
dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x1 0x00000000>;
|
||||
|
||||
/* This drives busses 0 to 0xf */
|
||||
bus-range = <0x0 0xf>;
|
||||
|
@ -289,10 +297,10 @@
|
|||
ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x00000000 0x00000000 0x80000000
|
||||
0x01000000 0x00000000 0x00000000 0x0000000f 0x80000000 0x00000000 0x00010000>;
|
||||
|
||||
/* Inbound 2GB range starting at 0 */
|
||||
dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
|
||||
/* Inbound 4GB range starting at 0 */
|
||||
dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x1 0x00000000>;
|
||||
|
||||
/* This drives busses 10 to 0x1f */
|
||||
/* This drives busses 0x10 to 0x1f */
|
||||
bus-range = <0x10 0x1f>;
|
||||
|
||||
/* Legacy interrupts (note the weird polarity, the bridge seems
|
||||
|
@ -330,10 +338,10 @@
|
|||
ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x80000000 0x00000000 0x80000000
|
||||
0x01000000 0x00000000 0x00000000 0x0000000f 0x80010000 0x00000000 0x00010000>;
|
||||
|
||||
/* Inbound 2GB range starting at 0 */
|
||||
dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
|
||||
/* Inbound 4GB range starting at 0 */
|
||||
dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x1 0x00000000>;
|
||||
|
||||
/* This drives busses 10 to 0x1f */
|
||||
/* This drives busses 0x20 to 0x2f */
|
||||
bus-range = <0x20 0x2f>;
|
||||
|
||||
/* Legacy interrupts (note the weird polarity, the bridge seems
|
||||
|
@ -371,10 +379,10 @@
|
|||
ranges = <0x02000000 0x00000000 0x80000000 0x0000000f 0x00000000 0x00000000 0x80000000
|
||||
0x01000000 0x00000000 0x00000000 0x0000000f 0x80020000 0x00000000 0x00010000>;
|
||||
|
||||
/* Inbound 2GB range starting at 0 */
|
||||
dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
|
||||
/* Inbound 4GB range starting at 0 */
|
||||
dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x1 0x00000000>;
|
||||
|
||||
/* This drives busses 10 to 0x1f */
|
||||
/* This drives busses 0x30 to 0x3f */
|
||||
bus-range = <0x30 0x3f>;
|
||||
|
||||
/* Legacy interrupts (note the weird polarity, the bridge seems
|
||||
|
|
|
@ -272,6 +272,8 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
tx-fifo-size-gige = <16384>;
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x00000000>;
|
||||
rgmii-device = <&RGMII0>;
|
||||
|
@ -300,6 +302,8 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
tx-fifo-size-gige = <16384>;
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x00000000>;
|
||||
rgmii-device = <&RGMII0>;
|
||||
|
|
|
@ -59,6 +59,13 @@
|
|||
reg = <0xe0000000 0x00000200>;
|
||||
bus-frequency = <0>; /* Filled in by U-Boot */
|
||||
|
||||
pmc: power@b00 {
|
||||
compatible = "fsl,mpc8360-pmc", "fsl,mpc8349-pmc";
|
||||
reg = <0xb00 0x100 0xa00 0x100>;
|
||||
interrupts = <80 0x8>;
|
||||
interrupt-parent = <&ipic>;
|
||||
};
|
||||
|
||||
i2c@3000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
|
|
@ -227,6 +227,8 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
tx-fifo-size-gige = <16384>;
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x0000003f>; /* Start at 6 */
|
||||
rgmii-device = <&RGMII0>;
|
||||
|
@ -255,6 +257,8 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
tx-fifo-size-gige = <16384>;
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x00000000>;
|
||||
rgmii-device = <&RGMII0>;
|
||||
|
|
|
@ -79,6 +79,13 @@
|
|||
reg = <0x200 0x100>;
|
||||
};
|
||||
|
||||
pmc: power@b00 {
|
||||
compatible = "fsl,mpc8323-pmc", "fsl,mpc8349-pmc";
|
||||
reg = <0xb00 0x100 0xa00 0x100>;
|
||||
interrupts = <80 0x8>;
|
||||
interrupt-parent = <&ipic>;
|
||||
};
|
||||
|
||||
i2c@3000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -163,6 +170,7 @@
|
|||
fsl,channel-fifo-len = <24>;
|
||||
fsl,exec-units-mask = <0x4c>;
|
||||
fsl,descriptor-types-mask = <0x0122003f>;
|
||||
sleep = <&pmc 0x03000000>;
|
||||
};
|
||||
|
||||
ipic: pic@700 {
|
||||
|
@ -428,5 +436,6 @@
|
|||
0xe0008300 0x8>; /* config space access registers */
|
||||
compatible = "fsl,mpc8349-pci";
|
||||
device_type = "pci";
|
||||
sleep = <&pmc 0x00010000>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -62,6 +62,13 @@
|
|||
reg = <0x200 0x100>;
|
||||
};
|
||||
|
||||
pmc: power@b00 {
|
||||
compatible = "fsl,mpc8323-pmc", "fsl,mpc8349-pmc";
|
||||
reg = <0xb00 0x100 0xa00 0x100>;
|
||||
interrupts = <80 0x8>;
|
||||
interrupt-parent = <&ipic>;
|
||||
};
|
||||
|
||||
i2c@3000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -141,6 +148,7 @@
|
|||
fsl,channel-fifo-len = <24>;
|
||||
fsl,exec-units-mask = <0x4c>;
|
||||
fsl,descriptor-types-mask = <0x0122003f>;
|
||||
sleep = <&pmc 0x03000000>;
|
||||
};
|
||||
|
||||
ipic:pic@700 {
|
||||
|
@ -360,5 +368,6 @@
|
|||
0xe0008300 0x8>; /* config space access registers */
|
||||
compatible = "fsl,mpc8349-pci";
|
||||
device_type = "pci";
|
||||
sleep = <&pmc 0x00010000>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -99,6 +99,13 @@
|
|||
reg = <0x200 0x100>;
|
||||
};
|
||||
|
||||
pmc: power@b00 {
|
||||
compatible = "fsl,mpc8360-pmc", "fsl,mpc8349-pmc";
|
||||
reg = <0xb00 0x100 0xa00 0x100>;
|
||||
interrupts = <80 0x8>;
|
||||
interrupt-parent = <&ipic>;
|
||||
};
|
||||
|
||||
i2c@3000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -194,6 +201,7 @@
|
|||
fsl,channel-fifo-len = <24>;
|
||||
fsl,exec-units-mask = <0x7e>;
|
||||
fsl,descriptor-types-mask = <0x01010ebf>;
|
||||
sleep = <&pmc 0x03000000>;
|
||||
};
|
||||
|
||||
ipic: pic@700 {
|
||||
|
@ -470,5 +478,6 @@
|
|||
0xe0008300 0x8>; /* config space access registers */
|
||||
compatible = "fsl,mpc8349-pci";
|
||||
device_type = "pci";
|
||||
sleep = <&pmc 0x00010000>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -71,6 +71,13 @@
|
|||
reg = <0x200 0x100>;
|
||||
};
|
||||
|
||||
pmc: power@b00 {
|
||||
compatible = "fsl,mpc8360-pmc", "fsl,mpc8349-pmc";
|
||||
reg = <0xb00 0x100 0xa00 0x100>;
|
||||
interrupts = <80 0x8>;
|
||||
interrupt-parent = <&ipic>;
|
||||
};
|
||||
|
||||
i2c@3000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -161,6 +168,7 @@
|
|||
fsl,channel-fifo-len = <24>;
|
||||
fsl,exec-units-mask = <0x7e>;
|
||||
fsl,descriptor-types-mask = <0x01010ebf>;
|
||||
sleep = <&pmc 0x03000000>;
|
||||
};
|
||||
|
||||
ipic: interrupt-controller@700 {
|
||||
|
@ -455,6 +463,7 @@
|
|||
0xa800 0 0 2 &ipic 20 8
|
||||
0xa800 0 0 3 &ipic 21 8
|
||||
0xa800 0 0 4 &ipic 18 8>;
|
||||
sleep = <&pmc 0x00010000>;
|
||||
/* filled by u-boot */
|
||||
bus-range = <0 0>;
|
||||
clock-frequency = <0>;
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
i-cache-line-size = <32>; // 32 bytes
|
||||
d-cache-size = <0x8000>; // L1, 32K
|
||||
i-cache-size = <0x8000>; // L1, 32K
|
||||
sleep = <&pmc 0x00008000 // core
|
||||
&pmc 0x00004000>; // timebase
|
||||
timebase-frequency = <0>;
|
||||
bus-frequency = <0>;
|
||||
clock-frequency = <0>;
|
||||
|
@ -94,31 +96,41 @@
|
|||
interrupts = <16 2>;
|
||||
};
|
||||
|
||||
i2c@3000 {
|
||||
i2c-sleep-nexus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <0>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3000 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
#size-cells = <1>;
|
||||
compatible = "simple-bus";
|
||||
sleep = <&pmc 0x00000004>;
|
||||
ranges;
|
||||
|
||||
rtc@68 {
|
||||
compatible = "dallas,ds1374";
|
||||
reg = <0x68>;
|
||||
i2c@3000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <0>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3000 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
|
||||
rtc@68 {
|
||||
compatible = "dallas,ds1374";
|
||||
reg = <0x68>;
|
||||
interrupts = <3 1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2c@3100 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <1>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3100 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
i2c@3100 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <1>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3100 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
};
|
||||
};
|
||||
|
||||
dma@21300 {
|
||||
|
@ -128,6 +140,8 @@
|
|||
reg = <0x21300 0x4>;
|
||||
ranges = <0x0 0x21100 0x200>;
|
||||
cell-index = <0>;
|
||||
sleep = <&pmc 0x00000400>;
|
||||
|
||||
dma-channel@0 {
|
||||
compatible = "fsl,mpc8568-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
|
@ -176,6 +190,7 @@
|
|||
interrupt-parent = <&mpic>;
|
||||
tbi-handle = <&tbi0>;
|
||||
phy-handle = <&phy2>;
|
||||
sleep = <&pmc 0x00000080>;
|
||||
|
||||
mdio@520 {
|
||||
#address-cells = <1>;
|
||||
|
@ -228,6 +243,7 @@
|
|||
interrupt-parent = <&mpic>;
|
||||
tbi-handle = <&tbi1>;
|
||||
phy-handle = <&phy3>;
|
||||
sleep = <&pmc 0x00000040>;
|
||||
|
||||
mdio@520 {
|
||||
#address-cells = <1>;
|
||||
|
@ -242,30 +258,47 @@
|
|||
};
|
||||
};
|
||||
|
||||
serial0: serial@4500 {
|
||||
cell-index = <0>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x4500 0x100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
duart-sleep-nexus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "simple-bus";
|
||||
sleep = <&pmc 0x00000002>;
|
||||
ranges;
|
||||
|
||||
serial0: serial@4500 {
|
||||
cell-index = <0>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x4500 0x100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
serial1: serial@4600 {
|
||||
cell-index = <1>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x4600 0x100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
};
|
||||
|
||||
global-utilities@e0000 { //global utilities block
|
||||
compatible = "fsl,mpc8548-guts";
|
||||
global-utilities@e0000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,mpc8568-guts", "fsl,mpc8548-guts";
|
||||
reg = <0xe0000 0x1000>;
|
||||
ranges = <0 0xe0000 0x1000>;
|
||||
fsl,has-rstcr;
|
||||
};
|
||||
|
||||
serial1: serial@4600 {
|
||||
cell-index = <1>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x4600 0x100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
pmc: power@70 {
|
||||
compatible = "fsl,mpc8568-pmc",
|
||||
"fsl,mpc8548-pmc";
|
||||
reg = <0x70 0x20>;
|
||||
};
|
||||
};
|
||||
|
||||
crypto@30000 {
|
||||
|
@ -277,6 +310,7 @@
|
|||
fsl,channel-fifo-len = <24>;
|
||||
fsl,exec-units-mask = <0xfe>;
|
||||
fsl,descriptor-types-mask = <0x12b0ebf>;
|
||||
sleep = <&pmc 0x01000000>;
|
||||
};
|
||||
|
||||
mpic: pic@40000 {
|
||||
|
@ -376,6 +410,7 @@
|
|||
compatible = "fsl,qe";
|
||||
ranges = <0x0 0xe0080000 0x40000>;
|
||||
reg = <0xe0080000 0x480>;
|
||||
sleep = <&pmc 0x00000800>;
|
||||
brg-frequency = <0>;
|
||||
bus-frequency = <396000000>;
|
||||
fsl,qe-num-riscs = <2>;
|
||||
|
@ -509,6 +544,7 @@
|
|||
bus-range = <0 255>;
|
||||
ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x0 0xe2000000 0x0 0x800000>;
|
||||
sleep = <&pmc 0x80000000>;
|
||||
clock-frequency = <66666666>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
|
@ -534,6 +570,7 @@
|
|||
bus-range = <0 255>;
|
||||
ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
|
||||
0x1000000 0x0 0x0 0xe2800000 0x0 0x800000>;
|
||||
sleep = <&pmc 0x20000000>;
|
||||
clock-frequency = <33333333>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
|
@ -570,5 +607,7 @@
|
|||
55 2 /* msg2_tx */
|
||||
56 2 /* msg2_rx */>;
|
||||
interrupt-parent = <&mpic>;
|
||||
sleep = <&pmc 0x00080000 /* controller */
|
||||
&pmc 0x00040000>; /* message unit */
|
||||
};
|
||||
};
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
i-cache-line-size = <32>; // 32 bytes
|
||||
d-cache-size = <0x8000>; // L1, 32K
|
||||
i-cache-size = <0x8000>; // L1, 32K
|
||||
sleep = <&pmc 0x00008000 // core
|
||||
&pmc 0x00004000>; // timebase
|
||||
timebase-frequency = <0>;
|
||||
bus-frequency = <0>;
|
||||
clock-frequency = <0>;
|
||||
|
@ -59,6 +61,7 @@
|
|||
reg = <0xe0005000 0x1000>;
|
||||
interrupts = <19 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
sleep = <&pmc 0x08000000>;
|
||||
|
||||
ranges = <0x0 0x0 0xfe000000 0x02000000
|
||||
0x1 0x0 0xf8000000 0x00008000
|
||||
|
@ -158,51 +161,69 @@
|
|||
interrupts = <18 2>;
|
||||
};
|
||||
|
||||
i2c@3000 {
|
||||
i2c-sleep-nexus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <0>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3000 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
#size-cells = <1>;
|
||||
compatible = "simple-bus";
|
||||
sleep = <&pmc 0x00000004>;
|
||||
ranges;
|
||||
|
||||
rtc@68 {
|
||||
compatible = "dallas,ds1374";
|
||||
reg = <0x68>;
|
||||
i2c@3000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <0>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3000 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
|
||||
rtc@68 {
|
||||
compatible = "dallas,ds1374";
|
||||
reg = <0x68>;
|
||||
interrupts = <3 1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c@3100 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <1>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3100 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
};
|
||||
};
|
||||
|
||||
i2c@3100 {
|
||||
duart-sleep-nexus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <1>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3100 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
};
|
||||
#size-cells = <1>;
|
||||
compatible = "simple-bus";
|
||||
sleep = <&pmc 0x00000002>;
|
||||
ranges;
|
||||
|
||||
serial0: serial@4500 {
|
||||
cell-index = <0>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x4500 0x100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
serial0: serial@4500 {
|
||||
cell-index = <0>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x4500 0x100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
serial1: serial@4600 {
|
||||
cell-index = <1>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x4600 0x100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
serial1: serial@4600 {
|
||||
cell-index = <1>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x4600 0x100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
};
|
||||
|
||||
L2: l2-cache-controller@20000 {
|
||||
|
@ -260,6 +281,7 @@
|
|||
reg = <0x2e000 0x1000>;
|
||||
interrupts = <72 0x8>;
|
||||
interrupt-parent = <&mpic>;
|
||||
sleep = <&pmc 0x00200000>;
|
||||
/* Filled in by U-Boot */
|
||||
clock-frequency = <0>;
|
||||
status = "disabled";
|
||||
|
@ -276,6 +298,7 @@
|
|||
fsl,channel-fifo-len = <24>;
|
||||
fsl,exec-units-mask = <0xbfe>;
|
||||
fsl,descriptor-types-mask = <0x3ab0ebf>;
|
||||
sleep = <&pmc 0x01000000>;
|
||||
};
|
||||
|
||||
mpic: pic@40000 {
|
||||
|
@ -304,9 +327,18 @@
|
|||
};
|
||||
|
||||
global-utilities@e0000 {
|
||||
compatible = "fsl,mpc8569-guts";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,mpc8569-guts", "fsl,mpc8548-guts";
|
||||
reg = <0xe0000 0x1000>;
|
||||
ranges = <0 0xe0000 0x1000>;
|
||||
fsl,has-rstcr;
|
||||
|
||||
pmc: power@70 {
|
||||
compatible = "fsl,mpc8569-pmc",
|
||||
"fsl,mpc8548-pmc";
|
||||
reg = <0x70 0x20>;
|
||||
};
|
||||
};
|
||||
|
||||
par_io@e0100 {
|
||||
|
@ -422,6 +454,7 @@
|
|||
compatible = "fsl,qe";
|
||||
ranges = <0x0 0xe0080000 0x40000>;
|
||||
reg = <0xe0080000 0x480>;
|
||||
sleep = <&pmc 0x00000800>;
|
||||
brg-frequency = <0>;
|
||||
bus-frequency = <0>;
|
||||
fsl,qe-num-riscs = <4>;
|
||||
|
@ -684,6 +717,7 @@
|
|||
bus-range = <0 255>;
|
||||
ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
|
||||
0x1000000 0x0 0x00000000 0xe2800000 0x0 0x00800000>;
|
||||
sleep = <&pmc 0x20000000>;
|
||||
clock-frequency = <33333333>;
|
||||
pcie@0 {
|
||||
reg = <0x0 0x0 0x0 0x0 0x0>;
|
||||
|
@ -714,5 +748,6 @@
|
|||
55 2 /* msg2_tx */
|
||||
56 2 /* msg2_rx */>;
|
||||
interrupt-parent = <&mpic>;
|
||||
sleep = <&pmc 0x00080000>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
i-cache-line-size = <32>;
|
||||
d-cache-size = <32768>; // L1
|
||||
i-cache-size = <32768>; // L1
|
||||
sleep = <&pmc 0x00008000 0 // core
|
||||
&pmc 0x00004000 0>; // timebase
|
||||
timebase-frequency = <0>; // From uboot
|
||||
bus-frequency = <0>; // From uboot
|
||||
clock-frequency = <0>; // From uboot
|
||||
|
@ -60,6 +62,7 @@
|
|||
5 0 0xe8480000 0x00008000
|
||||
6 0 0xe84c0000 0x00008000
|
||||
3 0 0xe8000000 0x00000020>;
|
||||
sleep = <&pmc 0x08000000 0>;
|
||||
|
||||
flash@0,0 {
|
||||
compatible = "cfi-flash";
|
||||
|
@ -105,6 +108,8 @@
|
|||
compatible = "fsl,fpga-pixis";
|
||||
reg = <3 0 0x20>;
|
||||
ranges = <0 3 0 0x20>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <8 8>;
|
||||
|
||||
sdcsr_pio: gpio-controller@a {
|
||||
#gpio-cells = <2>;
|
||||
|
@ -163,6 +168,7 @@
|
|||
reg = <0x3100 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
sleep = <&pmc 0x00000004 0>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
|
@ -174,6 +180,7 @@
|
|||
clock-frequency = <0>;
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
sleep = <&pmc 0x00000002 0>;
|
||||
};
|
||||
|
||||
serial1: serial@4600 {
|
||||
|
@ -184,6 +191,7 @@
|
|||
clock-frequency = <0>;
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
sleep = <&pmc 0x00000008 0>;
|
||||
};
|
||||
|
||||
spi@7000 {
|
||||
|
@ -196,6 +204,7 @@
|
|||
interrupt-parent = <&mpic>;
|
||||
mode = "cpu";
|
||||
gpios = <&sdcsr_pio 7 0>;
|
||||
sleep = <&pmc 0x00000800 0>;
|
||||
|
||||
mmc-slot@0 {
|
||||
compatible = "fsl,mpc8610hpcd-mmc-slot",
|
||||
|
@ -213,6 +222,7 @@
|
|||
reg = <0x2c000 100>;
|
||||
interrupts = <72 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
sleep = <&pmc 0x04000000 0>;
|
||||
};
|
||||
|
||||
mpic: interrupt-controller@40000 {
|
||||
|
@ -241,9 +251,18 @@
|
|||
};
|
||||
|
||||
global-utilities@e0000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,mpc8610-guts";
|
||||
reg = <0xe0000 0x1000>;
|
||||
ranges = <0 0xe0000 0x1000>;
|
||||
fsl,has-rstcr;
|
||||
|
||||
pmc: power@70 {
|
||||
compatible = "fsl,mpc8610-pmc",
|
||||
"fsl,mpc8641d-pmc";
|
||||
reg = <0x70 0x20>;
|
||||
};
|
||||
};
|
||||
|
||||
wdt@e4000 {
|
||||
|
@ -262,6 +281,7 @@
|
|||
fsl,playback-dma = <&dma00>;
|
||||
fsl,capture-dma = <&dma01>;
|
||||
fsl,fifo-depth = <8>;
|
||||
sleep = <&pmc 0 0x08000000>;
|
||||
};
|
||||
|
||||
ssi@16100 {
|
||||
|
@ -271,6 +291,7 @@
|
|||
interrupt-parent = <&mpic>;
|
||||
interrupts = <63 2>;
|
||||
fsl,fifo-depth = <8>;
|
||||
sleep = <&pmc 0 0x04000000>;
|
||||
};
|
||||
|
||||
dma@21300 {
|
||||
|
@ -280,6 +301,7 @@
|
|||
cell-index = <0>;
|
||||
reg = <0x21300 0x4>; /* DMA general status register */
|
||||
ranges = <0x0 0x21100 0x200>;
|
||||
sleep = <&pmc 0x00000400 0>;
|
||||
|
||||
dma00: dma-channel@0 {
|
||||
compatible = "fsl,mpc8610-dma-channel",
|
||||
|
@ -322,6 +344,7 @@
|
|||
cell-index = <1>;
|
||||
reg = <0xc300 0x4>; /* DMA general status register */
|
||||
ranges = <0x0 0xc100 0x200>;
|
||||
sleep = <&pmc 0x00000200 0>;
|
||||
|
||||
dma-channel@0 {
|
||||
compatible = "fsl,mpc8610-dma-channel",
|
||||
|
@ -369,6 +392,7 @@
|
|||
bus-range = <0 0>;
|
||||
ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x10000000
|
||||
0x01000000 0x0 0x00000000 0xe1000000 0x0 0x00100000>;
|
||||
sleep = <&pmc 0x80000000 0>;
|
||||
clock-frequency = <33333333>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <24 2>;
|
||||
|
@ -398,6 +422,7 @@
|
|||
bus-range = <1 3>;
|
||||
ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
|
||||
0x01000000 0x0 0x00000000 0xe3000000 0x0 0x00100000>;
|
||||
sleep = <&pmc 0x40000000 0>;
|
||||
clock-frequency = <33333333>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <26 2>;
|
||||
|
@ -474,6 +499,7 @@
|
|||
0x0000 0 0 4 &mpic 7 1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <25 2>;
|
||||
sleep = <&pmc 0x20000000 0>;
|
||||
clock-frequency = <33333333>;
|
||||
};
|
||||
};
|
||||
|
|
477
arch/powerpc/boot/dts/p1020rdb.dts
Normal file
477
arch/powerpc/boot/dts/p1020rdb.dts
Normal file
|
@ -0,0 +1,477 @@
|
|||
/*
|
||||
* P1020 RDB Device Tree Source
|
||||
*
|
||||
* Copyright 2009 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.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/ {
|
||||
model = "fsl,P1020";
|
||||
compatible = "fsl,P1020RDB";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
aliases {
|
||||
serial0 = &serial0;
|
||||
serial1 = &serial1;
|
||||
pci0 = &pci0;
|
||||
pci1 = &pci1;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
PowerPC,P1020@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0x0>;
|
||||
next-level-cache = <&L2>;
|
||||
};
|
||||
|
||||
PowerPC,P1020@1 {
|
||||
device_type = "cpu";
|
||||
reg = <0x1>;
|
||||
next-level-cache = <&L2>;
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
};
|
||||
|
||||
localbus@ffe05000 {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,p1020-elbc", "fsl,elbc", "simple-bus";
|
||||
reg = <0 0xffe05000 0 0x1000>;
|
||||
interrupts = <19 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
|
||||
/* NOR, NAND Flashes and Vitesse 5 port L2 switch */
|
||||
ranges = <0x0 0x0 0x0 0xef000000 0x01000000
|
||||
0x1 0x0 0x0 0xffa00000 0x00040000
|
||||
0x2 0x0 0x0 0xffb00000 0x00020000>;
|
||||
|
||||
nor@0,0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "cfi-flash";
|
||||
reg = <0x0 0x0 0x1000000>;
|
||||
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 (RO) Vitesse-7385 Firmware";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@40000 {
|
||||
/* 256KB for DTB Image */
|
||||
reg = <0x00040000 0x00040000>;
|
||||
label = "NOR (RO) DTB Image";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@80000 {
|
||||
/* 3.5 MB for Linux Kernel Image */
|
||||
reg = <0x00080000 0x00380000>;
|
||||
label = "NOR (RO) Linux Kernel Image";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@400000 {
|
||||
/* 11MB for JFFS2 based Root file System */
|
||||
reg = <0x00400000 0x00b00000>;
|
||||
label = "NOR (RW) JFFS2 Root File System";
|
||||
};
|
||||
|
||||
partition@f00000 {
|
||||
/* This location must not be altered */
|
||||
/* 512KB for u-boot Bootloader Image */
|
||||
/* 512KB for u-boot Environment Variables */
|
||||
reg = <0x00f00000 0x00100000>;
|
||||
label = "NOR (RO) U-Boot Image";
|
||||
read-only;
|
||||
};
|
||||
};
|
||||
|
||||
nand@1,0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,p1020-fcm-nand",
|
||||
"fsl,elbc-fcm-nand";
|
||||
reg = <0x1 0x0 0x40000>;
|
||||
|
||||
partition@0 {
|
||||
/* This location must not be altered */
|
||||
/* 1MB for u-boot Bootloader Image */
|
||||
reg = <0x0 0x00100000>;
|
||||
label = "NAND (RO) U-Boot Image";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@100000 {
|
||||
/* 1MB for DTB Image */
|
||||
reg = <0x00100000 0x00100000>;
|
||||
label = "NAND (RO) DTB Image";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@200000 {
|
||||
/* 4MB for Linux Kernel Image */
|
||||
reg = <0x00200000 0x00400000>;
|
||||
label = "NAND (RO) Linux Kernel Image";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@600000 {
|
||||
/* 4MB for Compressed Root file System Image */
|
||||
reg = <0x00600000 0x00400000>;
|
||||
label = "NAND (RO) Compressed RFS Image";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@a00000 {
|
||||
/* 7MB for JFFS2 based Root file System */
|
||||
reg = <0x00a00000 0x00700000>;
|
||||
label = "NAND (RW) JFFS2 Root File System";
|
||||
};
|
||||
|
||||
partition@1100000 {
|
||||
/* 15MB for JFFS2 based Root file System */
|
||||
reg = <0x01100000 0x00f00000>;
|
||||
label = "NAND (RW) Writable User area";
|
||||
};
|
||||
};
|
||||
|
||||
L2switch@2,0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "vitesse-7385";
|
||||
reg = <0x2 0x0 0x20000>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
soc@ffe00000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "fsl,p1020-immr", "simple-bus";
|
||||
ranges = <0x0 0x0 0xffe00000 0x100000>;
|
||||
bus-frequency = <0>; // Filled out by uboot.
|
||||
|
||||
ecm-law@0 {
|
||||
compatible = "fsl,ecm-law";
|
||||
reg = <0x0 0x1000>;
|
||||
fsl,num-laws = <12>;
|
||||
};
|
||||
|
||||
ecm@1000 {
|
||||
compatible = "fsl,p1020-ecm", "fsl,ecm";
|
||||
reg = <0x1000 0x1000>;
|
||||
interrupts = <16 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
memory-controller@2000 {
|
||||
compatible = "fsl,p1020-memory-controller";
|
||||
reg = <0x2000 0x1000>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <16 2>;
|
||||
};
|
||||
|
||||
i2c@3000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <0>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3000 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
rtc@68 {
|
||||
compatible = "dallas,ds1339";
|
||||
reg = <0x68>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c@3100 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <1>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3100 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
serial0: serial@4500 {
|
||||
cell-index = <0>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x4500 0x100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
serial1: serial@4600 {
|
||||
cell-index = <1>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x4600 0x100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
spi@7000 {
|
||||
cell-index = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl,espi";
|
||||
reg = <0x7000 0x1000>;
|
||||
interrupts = <59 0x2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
mode = "cpu";
|
||||
|
||||
fsl_m25p80@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,espi-flash";
|
||||
reg = <0>;
|
||||
linux,modalias = "fsl_m25p80";
|
||||
modal = "s25sl128b";
|
||||
spi-max-frequency = <50000000>;
|
||||
mode = <0>;
|
||||
|
||||
partition@0 {
|
||||
/* 512KB for u-boot Bootloader Image */
|
||||
reg = <0x0 0x00080000>;
|
||||
label = "SPI (RO) U-Boot Image";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@80000 {
|
||||
/* 512KB for DTB Image */
|
||||
reg = <0x00080000 0x00080000>;
|
||||
label = "SPI (RO) DTB Image";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@100000 {
|
||||
/* 4MB for Linux Kernel Image */
|
||||
reg = <0x00100000 0x00400000>;
|
||||
label = "SPI (RO) Linux Kernel Image";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@500000 {
|
||||
/* 4MB for Compressed RFS Image */
|
||||
reg = <0x00500000 0x00400000>;
|
||||
label = "SPI (RO) Compressed RFS Image";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@900000 {
|
||||
/* 7MB for JFFS2 based RFS */
|
||||
reg = <0x00900000 0x00700000>;
|
||||
label = "SPI (RW) JFFS2 RFS";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gpio: gpio-controller@f000 {
|
||||
#gpio-cells = <2>;
|
||||
compatible = "fsl,mpc8572-gpio";
|
||||
reg = <0xf000 0x100>;
|
||||
interrupts = <47 0x2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
gpio-controller;
|
||||
};
|
||||
|
||||
L2: l2-cache-controller@20000 {
|
||||
compatible = "fsl,p1020-l2-cache-controller";
|
||||
reg = <0x20000 0x1000>;
|
||||
cache-line-size = <32>; // 32 bytes
|
||||
cache-size = <0x40000>; // L2,256K
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <16 2>;
|
||||
};
|
||||
|
||||
dma@21300 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,eloplus-dma";
|
||||
reg = <0x21300 0x4>;
|
||||
ranges = <0x0 0x21100 0x200>;
|
||||
cell-index = <0>;
|
||||
dma-channel@0 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x0 0x80>;
|
||||
cell-index = <0>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <20 2>;
|
||||
};
|
||||
dma-channel@80 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x80 0x80>;
|
||||
cell-index = <1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <21 2>;
|
||||
};
|
||||
dma-channel@100 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x100 0x80>;
|
||||
cell-index = <2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <22 2>;
|
||||
};
|
||||
dma-channel@180 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x180 0x80>;
|
||||
cell-index = <3>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <23 2>;
|
||||
};
|
||||
};
|
||||
|
||||
usb@22000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl-usb2-dr";
|
||||
reg = <0x22000 0x1000>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <28 0x2>;
|
||||
phy_type = "ulpi";
|
||||
};
|
||||
|
||||
usb@23000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl-usb2-dr";
|
||||
reg = <0x23000 0x1000>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <46 0x2>;
|
||||
phy_type = "ulpi";
|
||||
};
|
||||
|
||||
sdhci@2e000 {
|
||||
compatible = "fsl,p1020-esdhc", "fsl,esdhc";
|
||||
reg = <0x2e000 0x1000>;
|
||||
interrupts = <72 0x2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
/* Filled in by U-Boot */
|
||||
clock-frequency = <0>;
|
||||
};
|
||||
|
||||
crypto@30000 {
|
||||
compatible = "fsl,sec3.1", "fsl,sec3.0", "fsl,sec2.4",
|
||||
"fsl,sec2.2", "fsl,sec2.1", "fsl,sec2.0";
|
||||
reg = <0x30000 0x10000>;
|
||||
interrupts = <45 2 58 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
fsl,num-channels = <4>;
|
||||
fsl,channel-fifo-len = <24>;
|
||||
fsl,exec-units-mask = <0xbfe>;
|
||||
fsl,descriptor-types-mask = <0x3ab0ebf>;
|
||||
};
|
||||
|
||||
mpic: pic@40000 {
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <0x40000 0x40000>;
|
||||
compatible = "chrp,open-pic";
|
||||
device_type = "open-pic";
|
||||
};
|
||||
|
||||
msi@41600 {
|
||||
compatible = "fsl,p1020-msi", "fsl,mpic-msi";
|
||||
reg = <0x41600 0x80>;
|
||||
msi-available-ranges = <0 0x100>;
|
||||
interrupts = <
|
||||
0xe0 0
|
||||
0xe1 0
|
||||
0xe2 0
|
||||
0xe3 0
|
||||
0xe4 0
|
||||
0xe5 0
|
||||
0xe6 0
|
||||
0xe7 0>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
global-utilities@e0000 { //global utilities block
|
||||
compatible = "fsl,p1020-guts";
|
||||
reg = <0xe0000 0x1000>;
|
||||
fsl,has-rstcr;
|
||||
};
|
||||
};
|
||||
|
||||
pci0: pcie@ffe09000 {
|
||||
compatible = "fsl,mpc8548-pcie";
|
||||
device_type = "pci";
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <0 0xffe09000 0 0x1000>;
|
||||
bus-range = <0 255>;
|
||||
ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>;
|
||||
clock-frequency = <33333333>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <16 2>;
|
||||
pcie@0 {
|
||||
reg = <0x0 0x0 0x0 0x0 0x0>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
device_type = "pci";
|
||||
ranges = <0x2000000 0x0 0xa0000000
|
||||
0x2000000 0x0 0xa0000000
|
||||
0x0 0x20000000
|
||||
|
||||
0x1000000 0x0 0x0
|
||||
0x1000000 0x0 0x0
|
||||
0x0 0x100000>;
|
||||
};
|
||||
};
|
||||
|
||||
pci1: pcie@ffe0a000 {
|
||||
compatible = "fsl,mpc8548-pcie";
|
||||
device_type = "pci";
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <0 0xffe0a000 0 0x1000>;
|
||||
bus-range = <0 255>;
|
||||
ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>;
|
||||
clock-frequency = <33333333>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <16 2>;
|
||||
pcie@0 {
|
||||
reg = <0x0 0x0 0x0 0x0 0x0>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
device_type = "pci";
|
||||
ranges = <0x2000000 0x0 0xc0000000
|
||||
0x2000000 0x0 0xc0000000
|
||||
0x0 0x20000000
|
||||
|
||||
0x1000000 0x0 0x0
|
||||
0x1000000 0x0 0x0
|
||||
0x0 0x100000>;
|
||||
};
|
||||
};
|
||||
};
|
363
arch/powerpc/boot/dts/p2020rdb_camp_core0.dts
Normal file
363
arch/powerpc/boot/dts/p2020rdb_camp_core0.dts
Normal file
|
@ -0,0 +1,363 @@
|
|||
/*
|
||||
* P2020 RDB Core0 Device Tree Source in CAMP mode.
|
||||
*
|
||||
* In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
|
||||
* can be shared, all the other devices must be assigned to one core only.
|
||||
* This dts file allows core0 to have memory, l2, i2c, spi, gpio, dma1, usb,
|
||||
* eth1, eth2, sdhc, crypto, global-util, pci0.
|
||||
*
|
||||
* Copyright 2009 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.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/ {
|
||||
model = "fsl,P2020";
|
||||
compatible = "fsl,P2020RDB", "fsl,MPC85XXRDB-CAMP";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
aliases {
|
||||
ethernet1 = &enet1;
|
||||
ethernet2 = &enet2;
|
||||
serial0 = &serial0;
|
||||
pci0 = &pci0;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
PowerPC,P2020@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0x0>;
|
||||
next-level-cache = <&L2>;
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
};
|
||||
|
||||
soc@ffe00000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "fsl,p2020-immr", "simple-bus";
|
||||
ranges = <0x0 0x0 0xffe00000 0x100000>;
|
||||
bus-frequency = <0>; // Filled out by uboot.
|
||||
|
||||
ecm-law@0 {
|
||||
compatible = "fsl,ecm-law";
|
||||
reg = <0x0 0x1000>;
|
||||
fsl,num-laws = <12>;
|
||||
};
|
||||
|
||||
ecm@1000 {
|
||||
compatible = "fsl,p2020-ecm", "fsl,ecm";
|
||||
reg = <0x1000 0x1000>;
|
||||
interrupts = <17 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
memory-controller@2000 {
|
||||
compatible = "fsl,p2020-memory-controller";
|
||||
reg = <0x2000 0x1000>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <18 2>;
|
||||
};
|
||||
|
||||
i2c@3000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <0>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3000 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
rtc@68 {
|
||||
compatible = "dallas,ds1339";
|
||||
reg = <0x68>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c@3100 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <1>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3100 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
serial0: serial@4500 {
|
||||
cell-index = <0>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x4500 0x100>;
|
||||
clock-frequency = <0>;
|
||||
};
|
||||
|
||||
spi@7000 {
|
||||
cell-index = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl,espi";
|
||||
reg = <0x7000 0x1000>;
|
||||
interrupts = <59 0x2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
mode = "cpu";
|
||||
|
||||
fsl_m25p80@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,espi-flash";
|
||||
reg = <0>;
|
||||
linux,modalias = "fsl_m25p80";
|
||||
modal = "s25sl128b";
|
||||
spi-max-frequency = <50000000>;
|
||||
mode = <0>;
|
||||
|
||||
partition@0 {
|
||||
/* 512KB for u-boot Bootloader Image */
|
||||
reg = <0x0 0x00080000>;
|
||||
label = "SPI (RO) U-Boot Image";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@80000 {
|
||||
/* 512KB for DTB Image */
|
||||
reg = <0x00080000 0x00080000>;
|
||||
label = "SPI (RO) DTB Image";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@100000 {
|
||||
/* 4MB for Linux Kernel Image */
|
||||
reg = <0x00100000 0x00400000>;
|
||||
label = "SPI (RO) Linux Kernel Image";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@500000 {
|
||||
/* 4MB for Compressed RFS Image */
|
||||
reg = <0x00500000 0x00400000>;
|
||||
label = "SPI (RO) Compressed RFS Image";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@900000 {
|
||||
/* 7MB for JFFS2 based RFS */
|
||||
reg = <0x00900000 0x00700000>;
|
||||
label = "SPI (RW) JFFS2 RFS";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gpio: gpio-controller@f000 {
|
||||
#gpio-cells = <2>;
|
||||
compatible = "fsl,mpc8572-gpio";
|
||||
reg = <0xf000 0x100>;
|
||||
interrupts = <47 0x2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
gpio-controller;
|
||||
};
|
||||
|
||||
L2: l2-cache-controller@20000 {
|
||||
compatible = "fsl,p2020-l2-cache-controller";
|
||||
reg = <0x20000 0x1000>;
|
||||
cache-line-size = <32>; // 32 bytes
|
||||
cache-size = <0x80000>; // L2,512K
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <16 2>;
|
||||
};
|
||||
|
||||
dma@21300 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,eloplus-dma";
|
||||
reg = <0x21300 0x4>;
|
||||
ranges = <0x0 0x21100 0x200>;
|
||||
cell-index = <0>;
|
||||
dma-channel@0 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x0 0x80>;
|
||||
cell-index = <0>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <20 2>;
|
||||
};
|
||||
dma-channel@80 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x80 0x80>;
|
||||
cell-index = <1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <21 2>;
|
||||
};
|
||||
dma-channel@100 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x100 0x80>;
|
||||
cell-index = <2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <22 2>;
|
||||
};
|
||||
dma-channel@180 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x180 0x80>;
|
||||
cell-index = <3>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <23 2>;
|
||||
};
|
||||
};
|
||||
|
||||
usb@22000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl-usb2-dr";
|
||||
reg = <0x22000 0x1000>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <28 0x2>;
|
||||
phy_type = "ulpi";
|
||||
};
|
||||
|
||||
mdio@24520 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl,gianfar-mdio";
|
||||
reg = <0x24520 0x20>;
|
||||
|
||||
phy0: ethernet-phy@0 {
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <3 1>;
|
||||
reg = <0x0>;
|
||||
};
|
||||
phy1: ethernet-phy@1 {
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <3 1>;
|
||||
reg = <0x1>;
|
||||
};
|
||||
};
|
||||
|
||||
mdio@25520 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl,gianfar-tbi";
|
||||
reg = <0x26520 0x20>;
|
||||
|
||||
tbi0: tbi-phy@11 {
|
||||
reg = <0x11>;
|
||||
device_type = "tbi-phy";
|
||||
};
|
||||
};
|
||||
|
||||
enet1: ethernet@25000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
cell-index = <1>;
|
||||
device_type = "network";
|
||||
model = "eTSEC";
|
||||
compatible = "gianfar";
|
||||
reg = <0x25000 0x1000>;
|
||||
ranges = <0x0 0x25000 0x1000>;
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
interrupts = <35 2 36 2 40 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
tbi-handle = <&tbi0>;
|
||||
phy-handle = <&phy0>;
|
||||
phy-connection-type = "sgmii";
|
||||
|
||||
};
|
||||
|
||||
enet2: ethernet@26000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
cell-index = <2>;
|
||||
device_type = "network";
|
||||
model = "eTSEC";
|
||||
compatible = "gianfar";
|
||||
reg = <0x26000 0x1000>;
|
||||
ranges = <0x0 0x26000 0x1000>;
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
interrupts = <31 2 32 2 33 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
phy-handle = <&phy1>;
|
||||
phy-connection-type = "rgmii-id";
|
||||
};
|
||||
|
||||
sdhci@2e000 {
|
||||
compatible = "fsl,p2020-esdhc", "fsl,esdhc";
|
||||
reg = <0x2e000 0x1000>;
|
||||
interrupts = <72 0x2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
/* Filled in by U-Boot */
|
||||
clock-frequency = <0>;
|
||||
};
|
||||
|
||||
crypto@30000 {
|
||||
compatible = "fsl,sec3.1", "fsl,sec3.0", "fsl,sec2.4",
|
||||
"fsl,sec2.2", "fsl,sec2.1", "fsl,sec2.0";
|
||||
reg = <0x30000 0x10000>;
|
||||
interrupts = <45 2 58 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
fsl,num-channels = <4>;
|
||||
fsl,channel-fifo-len = <24>;
|
||||
fsl,exec-units-mask = <0xbfe>;
|
||||
fsl,descriptor-types-mask = <0x3ab0ebf>;
|
||||
};
|
||||
|
||||
mpic: pic@40000 {
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <0x40000 0x40000>;
|
||||
compatible = "chrp,open-pic";
|
||||
device_type = "open-pic";
|
||||
protected-sources = <
|
||||
42 76 77 78 79 /* serial1 , dma2 */
|
||||
29 30 34 26 /* enet0, pci1 */
|
||||
0xe0 0xe1 0xe2 0xe3 /* msi */
|
||||
0xe4 0xe5 0xe6 0xe7
|
||||
>;
|
||||
};
|
||||
|
||||
global-utilities@e0000 {
|
||||
compatible = "fsl,p2020-guts";
|
||||
reg = <0xe0000 0x1000>;
|
||||
fsl,has-rstcr;
|
||||
};
|
||||
};
|
||||
|
||||
pci0: pcie@ffe09000 {
|
||||
compatible = "fsl,mpc8548-pcie";
|
||||
device_type = "pci";
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <0 0xffe09000 0 0x1000>;
|
||||
bus-range = <0 255>;
|
||||
ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>;
|
||||
clock-frequency = <33333333>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <25 2>;
|
||||
pcie@0 {
|
||||
reg = <0x0 0x0 0x0 0x0 0x0>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
device_type = "pci";
|
||||
ranges = <0x2000000 0x0 0xa0000000
|
||||
0x2000000 0x0 0xa0000000
|
||||
0x0 0x20000000
|
||||
|
||||
0x1000000 0x0 0x0
|
||||
0x1000000 0x0 0x0
|
||||
0x0 0x100000>;
|
||||
};
|
||||
};
|
||||
};
|
184
arch/powerpc/boot/dts/p2020rdb_camp_core1.dts
Normal file
184
arch/powerpc/boot/dts/p2020rdb_camp_core1.dts
Normal file
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* P2020 RDB Core1 Device Tree Source in CAMP mode.
|
||||
*
|
||||
* In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
|
||||
* can be shared, all the other devices must be assigned to one core only.
|
||||
* This dts allows core1 to have l2, dma2, eth0, pci1, msi.
|
||||
*
|
||||
* Please note to add "-b 1" for core1's dts compiling.
|
||||
*
|
||||
* Copyright 2009 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.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/ {
|
||||
model = "fsl,P2020";
|
||||
compatible = "fsl,P2020RDB", "fsl,MPC85XXRDB-CAMP";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
aliases {
|
||||
ethernet0 = &enet0;
|
||||
serial0 = &serial0;
|
||||
pci1 = &pci1;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
PowerPC,P2020@1 {
|
||||
device_type = "cpu";
|
||||
reg = <0x1>;
|
||||
next-level-cache = <&L2>;
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
};
|
||||
|
||||
soc@ffe00000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "fsl,p2020-immr", "simple-bus";
|
||||
ranges = <0x0 0x0 0xffe00000 0x100000>;
|
||||
bus-frequency = <0>; // Filled out by uboot.
|
||||
|
||||
serial0: serial@4600 {
|
||||
cell-index = <1>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x4600 0x100>;
|
||||
clock-frequency = <0>;
|
||||
};
|
||||
|
||||
dma@c300 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,eloplus-dma";
|
||||
reg = <0xc300 0x4>;
|
||||
ranges = <0x0 0xc100 0x200>;
|
||||
cell-index = <1>;
|
||||
dma-channel@0 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x0 0x80>;
|
||||
cell-index = <0>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <76 2>;
|
||||
};
|
||||
dma-channel@80 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x80 0x80>;
|
||||
cell-index = <1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <77 2>;
|
||||
};
|
||||
dma-channel@100 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x100 0x80>;
|
||||
cell-index = <2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <78 2>;
|
||||
};
|
||||
dma-channel@180 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x180 0x80>;
|
||||
cell-index = <3>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <79 2>;
|
||||
};
|
||||
};
|
||||
|
||||
L2: l2-cache-controller@20000 {
|
||||
compatible = "fsl,p2020-l2-cache-controller";
|
||||
reg = <0x20000 0x1000>;
|
||||
cache-line-size = <32>; // 32 bytes
|
||||
cache-size = <0x80000>; // L2,512K
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
|
||||
enet0: ethernet@24000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
cell-index = <0>;
|
||||
device_type = "network";
|
||||
model = "eTSEC";
|
||||
compatible = "gianfar";
|
||||
reg = <0x24000 0x1000>;
|
||||
ranges = <0x0 0x24000 0x1000>;
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
interrupts = <29 2 30 2 34 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
fixed-link = <1 1 1000 0 0>;
|
||||
phy-connection-type = "rgmii-id";
|
||||
|
||||
};
|
||||
|
||||
mpic: pic@40000 {
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <0x40000 0x40000>;
|
||||
compatible = "chrp,open-pic";
|
||||
device_type = "open-pic";
|
||||
protected-sources = <
|
||||
17 18 43 42 59 47 /*ecm, mem, i2c, serial0, spi,gpio */
|
||||
16 20 21 22 23 28 /* L2, dma1, USB */
|
||||
03 35 36 40 31 32 33 /* mdio, enet1, enet2 */
|
||||
72 45 58 25 /* sdhci, crypto , pci */
|
||||
>;
|
||||
};
|
||||
|
||||
msi@41600 {
|
||||
compatible = "fsl,p2020-msi", "fsl,mpic-msi";
|
||||
reg = <0x41600 0x80>;
|
||||
msi-available-ranges = <0 0x100>;
|
||||
interrupts = <
|
||||
0xe0 0
|
||||
0xe1 0
|
||||
0xe2 0
|
||||
0xe3 0
|
||||
0xe4 0
|
||||
0xe5 0
|
||||
0xe6 0
|
||||
0xe7 0>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
};
|
||||
|
||||
pci1: pcie@ffe0a000 {
|
||||
compatible = "fsl,mpc8548-pcie";
|
||||
device_type = "pci";
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <0 0xffe0a000 0 0x1000>;
|
||||
bus-range = <0 255>;
|
||||
ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>;
|
||||
clock-frequency = <33333333>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <26 2>;
|
||||
pcie@0 {
|
||||
reg = <0x0 0x0 0x0 0x0 0x0>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
device_type = "pci";
|
||||
ranges = <0x2000000 0x0 0xc0000000
|
||||
0x2000000 0x0 0xc0000000
|
||||
0x0 0x20000000
|
||||
|
||||
0x1000000 0x0 0x0
|
||||
0x1000000 0x0 0x0
|
||||
0x0 0x100000>;
|
||||
};
|
||||
};
|
||||
};
|
554
arch/powerpc/boot/dts/p4080ds.dts
Normal file
554
arch/powerpc/boot/dts/p4080ds.dts
Normal file
|
@ -0,0 +1,554 @@
|
|||
/*
|
||||
* P4080DS Device Tree Source
|
||||
*
|
||||
* Copyright 2009 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.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
model = "fsl,P4080DS";
|
||||
compatible = "fsl,P4080DS";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
aliases {
|
||||
ccsr = &soc;
|
||||
|
||||
serial0 = &serial0;
|
||||
serial1 = &serial1;
|
||||
serial2 = &serial2;
|
||||
serial3 = &serial3;
|
||||
pci0 = &pci0;
|
||||
pci1 = &pci1;
|
||||
pci2 = &pci2;
|
||||
usb0 = &usb0;
|
||||
usb1 = &usb1;
|
||||
dma0 = &dma0;
|
||||
dma1 = &dma1;
|
||||
sdhc = &sdhc;
|
||||
|
||||
rio0 = &rapidio0;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu0: PowerPC,4080@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0>;
|
||||
next-level-cache = <&L2_0>;
|
||||
L2_0: l2-cache {
|
||||
};
|
||||
};
|
||||
cpu1: PowerPC,4080@1 {
|
||||
device_type = "cpu";
|
||||
reg = <1>;
|
||||
next-level-cache = <&L2_1>;
|
||||
L2_1: l2-cache {
|
||||
};
|
||||
};
|
||||
cpu2: PowerPC,4080@2 {
|
||||
device_type = "cpu";
|
||||
reg = <2>;
|
||||
next-level-cache = <&L2_2>;
|
||||
L2_2: l2-cache {
|
||||
};
|
||||
};
|
||||
cpu3: PowerPC,4080@3 {
|
||||
device_type = "cpu";
|
||||
reg = <3>;
|
||||
next-level-cache = <&L2_3>;
|
||||
L2_3: l2-cache {
|
||||
};
|
||||
};
|
||||
cpu4: PowerPC,4080@4 {
|
||||
device_type = "cpu";
|
||||
reg = <4>;
|
||||
next-level-cache = <&L2_4>;
|
||||
L2_4: l2-cache {
|
||||
};
|
||||
};
|
||||
cpu5: PowerPC,4080@5 {
|
||||
device_type = "cpu";
|
||||
reg = <5>;
|
||||
next-level-cache = <&L2_5>;
|
||||
L2_5: l2-cache {
|
||||
};
|
||||
};
|
||||
cpu6: PowerPC,4080@6 {
|
||||
device_type = "cpu";
|
||||
reg = <6>;
|
||||
next-level-cache = <&L2_6>;
|
||||
L2_6: l2-cache {
|
||||
};
|
||||
};
|
||||
cpu7: PowerPC,4080@7 {
|
||||
device_type = "cpu";
|
||||
reg = <7>;
|
||||
next-level-cache = <&L2_7>;
|
||||
L2_7: l2-cache {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
};
|
||||
|
||||
soc: soc@ffe000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
|
||||
reg = <0xf 0xfe000000 0 0x00001000>;
|
||||
|
||||
corenet-law@0 {
|
||||
compatible = "fsl,corenet-law";
|
||||
reg = <0x0 0x1000>;
|
||||
fsl,num-laws = <32>;
|
||||
};
|
||||
|
||||
memory-controller@8000 {
|
||||
compatible = "fsl,p4080-memory-controller";
|
||||
reg = <0x8000 0x1000>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <0x12 2>;
|
||||
};
|
||||
|
||||
memory-controller@9000 {
|
||||
compatible = "fsl,p4080-memory-controller";
|
||||
reg = <0x9000 0x1000>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <0x12 2>;
|
||||
};
|
||||
|
||||
corenet-cf@18000 {
|
||||
compatible = "fsl,corenet-cf";
|
||||
reg = <0x18000 0x1000>;
|
||||
fsl,ccf-num-csdids = <32>;
|
||||
fsl,ccf-num-snoopids = <32>;
|
||||
};
|
||||
|
||||
iommu@20000 {
|
||||
compatible = "fsl,p4080-pamu";
|
||||
reg = <0x20000 0x10000>;
|
||||
interrupts = <24 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
mpic: pic@40000 {
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <0x40000 0x40000>;
|
||||
compatible = "chrp,open-pic";
|
||||
device_type = "open-pic";
|
||||
};
|
||||
|
||||
dma0: dma@100300 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,p4080-dma", "fsl,eloplus-dma";
|
||||
reg = <0x100300 0x4>;
|
||||
ranges = <0x0 0x100100 0x200>;
|
||||
cell-index = <0>;
|
||||
dma-channel@0 {
|
||||
compatible = "fsl,p4080-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x0 0x80>;
|
||||
cell-index = <0>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <28 2>;
|
||||
};
|
||||
dma-channel@80 {
|
||||
compatible = "fsl,p4080-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x80 0x80>;
|
||||
cell-index = <1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <29 2>;
|
||||
};
|
||||
dma-channel@100 {
|
||||
compatible = "fsl,p4080-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x100 0x80>;
|
||||
cell-index = <2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <30 2>;
|
||||
};
|
||||
dma-channel@180 {
|
||||
compatible = "fsl,p4080-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x180 0x80>;
|
||||
cell-index = <3>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <31 2>;
|
||||
};
|
||||
};
|
||||
|
||||
dma1: dma@101300 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,p4080-dma", "fsl,eloplus-dma";
|
||||
reg = <0x101300 0x4>;
|
||||
ranges = <0x0 0x101100 0x200>;
|
||||
cell-index = <1>;
|
||||
dma-channel@0 {
|
||||
compatible = "fsl,p4080-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x0 0x80>;
|
||||
cell-index = <0>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <32 2>;
|
||||
};
|
||||
dma-channel@80 {
|
||||
compatible = "fsl,p4080-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x80 0x80>;
|
||||
cell-index = <1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <33 2>;
|
||||
};
|
||||
dma-channel@100 {
|
||||
compatible = "fsl,p4080-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x100 0x80>;
|
||||
cell-index = <2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <34 2>;
|
||||
};
|
||||
dma-channel@180 {
|
||||
compatible = "fsl,p4080-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x180 0x80>;
|
||||
cell-index = <3>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <35 2>;
|
||||
};
|
||||
};
|
||||
|
||||
spi@110000 {
|
||||
cell-index = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl,espi";
|
||||
reg = <0x110000 0x1000>;
|
||||
interrupts = <53 0x2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
espi,num-ss-bits = <4>;
|
||||
mode = "cpu";
|
||||
|
||||
fsl_m25p80@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,espi-flash";
|
||||
reg = <0>;
|
||||
linux,modalias = "fsl_m25p80";
|
||||
spi-max-frequency = <40000000>; /* input clock */
|
||||
partition@u-boot {
|
||||
label = "u-boot";
|
||||
reg = <0x00000000 0x00100000>;
|
||||
read-only;
|
||||
};
|
||||
partition@kernel {
|
||||
label = "kernel";
|
||||
reg = <0x00100000 0x00500000>;
|
||||
read-only;
|
||||
};
|
||||
partition@dtb {
|
||||
label = "dtb";
|
||||
reg = <0x00600000 0x00100000>;
|
||||
read-only;
|
||||
};
|
||||
partition@fs {
|
||||
label = "file system";
|
||||
reg = <0x00700000 0x00900000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sdhc: sdhc@114000 {
|
||||
compatible = "fsl,p4080-esdhc", "fsl,esdhc";
|
||||
reg = <0x114000 0x1000>;
|
||||
interrupts = <48 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
i2c@118000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <0>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x118000 0x100>;
|
||||
interrupts = <38 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
i2c@118100 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <1>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x118100 0x100>;
|
||||
interrupts = <38 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
eeprom@51 {
|
||||
compatible = "at24,24c256";
|
||||
reg = <0x51>;
|
||||
};
|
||||
eeprom@52 {
|
||||
compatible = "at24,24c256";
|
||||
reg = <0x52>;
|
||||
};
|
||||
rtc@68 {
|
||||
compatible = "dallas,ds3232";
|
||||
reg = <0x68>;
|
||||
interrupts = <0 0x1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c@119000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <2>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x119000 0x100>;
|
||||
interrupts = <39 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
i2c@119100 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <3>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x119100 0x100>;
|
||||
interrupts = <39 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
serial0: serial@11c500 {
|
||||
cell-index = <0>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x11c500 0x100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <36 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
serial1: serial@11c600 {
|
||||
cell-index = <1>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x11c600 0x100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <36 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
serial2: serial@11d500 {
|
||||
cell-index = <2>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x11d500 0x100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <37 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
serial3: serial@11d600 {
|
||||
cell-index = <3>;
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0x11d600 0x100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <37 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
gpio0: gpio@130000 {
|
||||
compatible = "fsl,p4080-gpio";
|
||||
reg = <0x130000 0x1000>;
|
||||
interrupts = <55 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
};
|
||||
|
||||
usb0: usb@210000 {
|
||||
compatible = "fsl,p4080-usb2-mph",
|
||||
"fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
|
||||
reg = <0x210000 0x1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <44 0x2>;
|
||||
phy_type = "ulpi";
|
||||
};
|
||||
|
||||
usb1: usb@211000 {
|
||||
compatible = "fsl,p4080-usb2-dr",
|
||||
"fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
|
||||
reg = <0x211000 0x1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <45 0x2>;
|
||||
dr_mode = "host";
|
||||
phy_type = "ulpi";
|
||||
};
|
||||
};
|
||||
|
||||
rapidio0: rapidio@ffe0c0000 {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
compatible = "fsl,rapidio-delta";
|
||||
reg = <0xf 0xfe0c0000 0 0x20000>;
|
||||
ranges = <0 0 0xf 0xf5000000 0 0x01000000>;
|
||||
interrupt-parent = <&mpic>;
|
||||
/* err_irq bell_outb_irq bell_inb_irq
|
||||
msg1_tx_irq msg1_rx_irq msg2_tx_irq msg2_rx_irq */
|
||||
interrupts = <16 2 56 2 57 2 60 2 61 2 62 2 63 2>;
|
||||
};
|
||||
|
||||
localbus@ffe124000 {
|
||||
compatible = "fsl,p4080-elbc", "fsl,elbc", "simple-bus";
|
||||
reg = <0xf 0xfe124000 0 0x1000>;
|
||||
interrupts = <25 2>;
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
|
||||
ranges = <0 0 0xf 0xe8000000 0x08000000>;
|
||||
|
||||
flash@0,0 {
|
||||
compatible = "cfi-flash";
|
||||
reg = <0 0 0x08000000>;
|
||||
bank-width = <2>;
|
||||
device-width = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
pci0: pcie@ffe200000 {
|
||||
compatible = "fsl,p4080-pcie";
|
||||
device_type = "pci";
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <0xf 0xfe200000 0 0x1000>;
|
||||
bus-range = <0x0 0xff>;
|
||||
ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
|
||||
0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
|
||||
clock-frequency = <0x1fca055>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <16 2>;
|
||||
|
||||
interrupt-map-mask = <0xf800 0 0 7>;
|
||||
interrupt-map = <
|
||||
/* IDSEL 0x0 */
|
||||
0000 0 0 1 &mpic 40 1
|
||||
0000 0 0 2 &mpic 1 1
|
||||
0000 0 0 3 &mpic 2 1
|
||||
0000 0 0 4 &mpic 3 1
|
||||
>;
|
||||
pcie@0 {
|
||||
reg = <0 0 0 0 0>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
device_type = "pci";
|
||||
ranges = <0x02000000 0 0xe0000000
|
||||
0x02000000 0 0xe0000000
|
||||
0 0x20000000
|
||||
|
||||
0x01000000 0 0x00000000
|
||||
0x01000000 0 0x00000000
|
||||
0 0x00010000>;
|
||||
};
|
||||
};
|
||||
|
||||
pci1: pcie@ffe201000 {
|
||||
compatible = "fsl,p4080-pcie";
|
||||
device_type = "pci";
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <0xf 0xfe201000 0 0x1000>;
|
||||
bus-range = <0 0xff>;
|
||||
ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
|
||||
0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
|
||||
clock-frequency = <0x1fca055>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <16 2>;
|
||||
interrupt-map-mask = <0xf800 0 0 7>;
|
||||
interrupt-map = <
|
||||
/* IDSEL 0x0 */
|
||||
0000 0 0 1 &mpic 41 1
|
||||
0000 0 0 2 &mpic 5 1
|
||||
0000 0 0 3 &mpic 6 1
|
||||
0000 0 0 4 &mpic 7 1
|
||||
>;
|
||||
pcie@0 {
|
||||
reg = <0 0 0 0 0>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
device_type = "pci";
|
||||
ranges = <0x02000000 0 0xe0000000
|
||||
0x02000000 0 0xe0000000
|
||||
0 0x20000000
|
||||
|
||||
0x01000000 0 0x00000000
|
||||
0x01000000 0 0x00000000
|
||||
0 0x00010000>;
|
||||
};
|
||||
};
|
||||
|
||||
pci2: pcie@ffe202000 {
|
||||
compatible = "fsl,p4080-pcie";
|
||||
device_type = "pci";
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <0xf 0xfe202000 0 0x1000>;
|
||||
bus-range = <0x0 0xff>;
|
||||
ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
|
||||
0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
|
||||
clock-frequency = <0x1fca055>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <16 2>;
|
||||
interrupt-map-mask = <0xf800 0 0 7>;
|
||||
interrupt-map = <
|
||||
/* IDSEL 0x0 */
|
||||
0000 0 0 1 &mpic 42 1
|
||||
0000 0 0 2 &mpic 9 1
|
||||
0000 0 0 3 &mpic 10 1
|
||||
0000 0 0 4 &mpic 11 1
|
||||
>;
|
||||
pcie@0 {
|
||||
reg = <0 0 0 0 0>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
device_type = "pci";
|
||||
ranges = <0x02000000 0 0xe0000000
|
||||
0x02000000 0 0xe0000000
|
||||
0 0x20000000
|
||||
|
||||
0x01000000 0 0x00000000
|
||||
0x01000000 0 0x00000000
|
||||
0 0x00010000>;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
|
@ -226,6 +226,7 @@
|
|||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
rx-fifo-size-gige = <16384>;
|
||||
phy-mode = "rgmii";
|
||||
phy-map = <0x00000000>;
|
||||
rgmii-device = <&RGMII0>;
|
||||
|
|
|
@ -282,20 +282,10 @@
|
|||
/* Inbound 2GB range starting at 0 */
|
||||
dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
|
||||
|
||||
/* Bamboo has all 4 IRQ pins tied together per slot */
|
||||
interrupt-map-mask = <0xf800 0x0 0x0 0x0>;
|
||||
interrupt-map = <
|
||||
/* IDSEL 1 */
|
||||
0x800 0x0 0x0 0x0 &UIC0 0x1c 0x8
|
||||
|
||||
/* IDSEL 2 */
|
||||
0x1000 0x0 0x0 0x0 &UIC0 0x1b 0x8
|
||||
|
||||
/* IDSEL 3 */
|
||||
0x1800 0x0 0x0 0x0 &UIC0 0x1a 0x8
|
||||
|
||||
/* IDSEL 4 */
|
||||
0x2000 0x0 0x0 0x0 &UIC0 0x19 0x8
|
||||
/* IDSEL 12 */
|
||||
0x6000 0x0 0x0 0x0 &UIC0 0x19 0x8
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -218,7 +218,7 @@ CONFIG_MPIC=y
|
|||
# CONFIG_MPIC_WEIRD is not set
|
||||
# CONFIG_PPC_I8259 is not set
|
||||
# CONFIG_PPC_RTAS is not set
|
||||
# CONFIG_MMIO_NVRAM is not set
|
||||
CONFIG_MMIO_NVRAM=y
|
||||
# CONFIG_PPC_MPC106 is not set
|
||||
# CONFIG_PPC_970_NAP is not set
|
||||
# CONFIG_PPC_INDIRECT_IO is not set
|
||||
|
|
|
@ -218,7 +218,7 @@ CONFIG_MPIC=y
|
|||
# CONFIG_MPIC_WEIRD is not set
|
||||
# CONFIG_PPC_I8259 is not set
|
||||
# CONFIG_PPC_RTAS is not set
|
||||
# CONFIG_MMIO_NVRAM is not set
|
||||
CONFIG_MMIO_NVRAM=y
|
||||
# CONFIG_PPC_MPC106 is not set
|
||||
# CONFIG_PPC_970_NAP is not set
|
||||
# CONFIG_PPC_INDIRECT_IO is not set
|
||||
|
|
|
@ -219,7 +219,7 @@ CONFIG_MPIC=y
|
|||
# CONFIG_MPIC_WEIRD is not set
|
||||
# CONFIG_PPC_I8259 is not set
|
||||
# CONFIG_PPC_RTAS is not set
|
||||
# CONFIG_MMIO_NVRAM is not set
|
||||
CONFIG_MMIO_NVRAM=y
|
||||
# CONFIG_PPC_MPC106 is not set
|
||||
# CONFIG_PPC_970_NAP is not set
|
||||
# CONFIG_PPC_INDIRECT_IO is not set
|
||||
|
@ -1124,7 +1124,7 @@ CONFIG_UNIX98_PTYS=y
|
|||
# CONFIG_IPMI_HANDLER is not set
|
||||
CONFIG_HW_RANDOM=y
|
||||
# CONFIG_HW_RANDOM_TIMERIOMEM is not set
|
||||
# CONFIG_NVRAM is not set
|
||||
CONFIG_NVRAM=y
|
||||
# CONFIG_R3964 is not set
|
||||
# CONFIG_APPLICOM is not set
|
||||
# CONFIG_RAW_DRIVER is not set
|
||||
|
|
|
@ -3,8 +3,47 @@
|
|||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
/*
|
||||
* USB Controller pram common to QE and CPM.
|
||||
*/
|
||||
struct usb_ctlr {
|
||||
u8 usb_usmod;
|
||||
u8 usb_usadr;
|
||||
u8 usb_uscom;
|
||||
u8 res1[1];
|
||||
__be16 usb_usep[4];
|
||||
u8 res2[4];
|
||||
__be16 usb_usber;
|
||||
u8 res3[2];
|
||||
__be16 usb_usbmr;
|
||||
u8 res4[1];
|
||||
u8 usb_usbs;
|
||||
/* Fields down below are QE-only */
|
||||
__be16 usb_ussft;
|
||||
u8 res5[2];
|
||||
__be16 usb_usfrn;
|
||||
u8 res6[0x22];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* Function code bits, usually generic to devices.
|
||||
*/
|
||||
#ifdef CONFIG_CPM1
|
||||
#define CPMFCR_GBL ((u_char)0x00) /* Flag doesn't exist in CPM1 */
|
||||
#define CPMFCR_TC2 ((u_char)0x00) /* Flag doesn't exist in CPM1 */
|
||||
#define CPMFCR_DTB ((u_char)0x00) /* Flag doesn't exist in CPM1 */
|
||||
#define CPMFCR_BDB ((u_char)0x00) /* Flag doesn't exist in CPM1 */
|
||||
#else
|
||||
#define CPMFCR_GBL ((u_char)0x20) /* Set memory snooping */
|
||||
#define CPMFCR_TC2 ((u_char)0x04) /* Transfer code 2 value */
|
||||
#define CPMFCR_DTB ((u_char)0x02) /* Use local bus for data when set */
|
||||
#define CPMFCR_BDB ((u_char)0x01) /* Use local bus for BD when set */
|
||||
#endif
|
||||
#define CPMFCR_EB ((u_char)0x10) /* Set big endian byte order */
|
||||
|
||||
/* Opcodes common to CPM1 and CPM2
|
||||
*/
|
||||
#define CPM_CR_INIT_TRX ((ushort)0x0000)
|
||||
|
@ -93,13 +132,56 @@ typedef struct cpm_buf_desc {
|
|||
#define BD_I2C_START (0x0400)
|
||||
|
||||
int cpm_muram_init(void);
|
||||
|
||||
#if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE)
|
||||
unsigned long cpm_muram_alloc(unsigned long size, unsigned long align);
|
||||
int cpm_muram_free(unsigned long offset);
|
||||
unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size);
|
||||
void __iomem *cpm_muram_addr(unsigned long offset);
|
||||
unsigned long cpm_muram_offset(void __iomem *addr);
|
||||
dma_addr_t cpm_muram_dma(void __iomem *addr);
|
||||
#else
|
||||
static inline unsigned long cpm_muram_alloc(unsigned long size,
|
||||
unsigned long align)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int cpm_muram_free(unsigned long offset)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline unsigned long cpm_muram_alloc_fixed(unsigned long offset,
|
||||
unsigned long size)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline void __iomem *cpm_muram_addr(unsigned long offset)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline unsigned long cpm_muram_offset(void __iomem *addr)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline dma_addr_t cpm_muram_dma(void __iomem *addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE) */
|
||||
|
||||
#ifdef CONFIG_CPM
|
||||
int cpm_command(u32 command, u8 opcode);
|
||||
#else
|
||||
static inline int cpm_command(u32 command, u8 opcode)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif /* CONFIG_CPM */
|
||||
|
||||
int cpm2_gpiochip_add32(struct device_node *np);
|
||||
|
||||
|
|
|
@ -478,51 +478,6 @@ typedef struct iic {
|
|||
char res2[2]; /* Reserved */
|
||||
} iic_t;
|
||||
|
||||
/* SPI parameter RAM.
|
||||
*/
|
||||
typedef struct spi {
|
||||
ushort spi_rbase; /* Rx Buffer descriptor base address */
|
||||
ushort spi_tbase; /* Tx Buffer descriptor base address */
|
||||
u_char spi_rfcr; /* Rx function code */
|
||||
u_char spi_tfcr; /* Tx function code */
|
||||
ushort spi_mrblr; /* Max receive buffer length */
|
||||
uint spi_rstate; /* Internal */
|
||||
uint spi_rdp; /* Internal */
|
||||
ushort spi_rbptr; /* Internal */
|
||||
ushort spi_rbc; /* Internal */
|
||||
uint spi_rxtmp; /* Internal */
|
||||
uint spi_tstate; /* Internal */
|
||||
uint spi_tdp; /* Internal */
|
||||
ushort spi_tbptr; /* Internal */
|
||||
ushort spi_tbc; /* Internal */
|
||||
uint spi_txtmp; /* Internal */
|
||||
uint spi_res;
|
||||
ushort spi_rpbase; /* Relocation pointer */
|
||||
ushort spi_res2;
|
||||
} spi_t;
|
||||
|
||||
/* SPI Mode register.
|
||||
*/
|
||||
#define SPMODE_LOOP ((ushort)0x4000) /* Loopback */
|
||||
#define SPMODE_CI ((ushort)0x2000) /* Clock Invert */
|
||||
#define SPMODE_CP ((ushort)0x1000) /* Clock Phase */
|
||||
#define SPMODE_DIV16 ((ushort)0x0800) /* BRG/16 mode */
|
||||
#define SPMODE_REV ((ushort)0x0400) /* Reversed Data */
|
||||
#define SPMODE_MSTR ((ushort)0x0200) /* SPI Master */
|
||||
#define SPMODE_EN ((ushort)0x0100) /* Enable */
|
||||
#define SPMODE_LENMSK ((ushort)0x00f0) /* character length */
|
||||
#define SPMODE_LEN4 ((ushort)0x0030) /* 4 bits per char */
|
||||
#define SPMODE_LEN8 ((ushort)0x0070) /* 8 bits per char */
|
||||
#define SPMODE_LEN16 ((ushort)0x00f0) /* 16 bits per char */
|
||||
#define SPMODE_PMMSK ((ushort)0x000f) /* prescale modulus */
|
||||
|
||||
/* SPIE fields */
|
||||
#define SPIE_MME 0x20
|
||||
#define SPIE_TXE 0x10
|
||||
#define SPIE_BSY 0x04
|
||||
#define SPIE_TXB 0x02
|
||||
#define SPIE_RXB 0x01
|
||||
|
||||
/*
|
||||
* RISC Controller Configuration Register definitons
|
||||
*/
|
||||
|
|
|
@ -124,14 +124,6 @@ static inline void cpm2_fastbrg(uint brg, uint rate, int div16)
|
|||
__cpm2_setbrg(brg, rate, CPM2_BRG_INT_CLK, div16, CPM_BRG_EXTC_INT);
|
||||
}
|
||||
|
||||
/* Function code bits, usually generic to devices.
|
||||
*/
|
||||
#define CPMFCR_GBL ((u_char)0x20) /* Set memory snooping */
|
||||
#define CPMFCR_EB ((u_char)0x10) /* Set big endian byte order */
|
||||
#define CPMFCR_TC2 ((u_char)0x04) /* Transfer code 2 value */
|
||||
#define CPMFCR_DTB ((u_char)0x02) /* Use local bus for data when set */
|
||||
#define CPMFCR_BDB ((u_char)0x01) /* Use local bus for BD when set */
|
||||
|
||||
/* Parameter RAM offsets from the base.
|
||||
*/
|
||||
#define PROFF_SCC1 ((uint)0x8000)
|
||||
|
@ -654,45 +646,6 @@ typedef struct iic {
|
|||
uint iic_txtmp; /* Internal */
|
||||
} iic_t;
|
||||
|
||||
/* SPI parameter RAM.
|
||||
*/
|
||||
typedef struct spi {
|
||||
ushort spi_rbase; /* Rx Buffer descriptor base address */
|
||||
ushort spi_tbase; /* Tx Buffer descriptor base address */
|
||||
u_char spi_rfcr; /* Rx function code */
|
||||
u_char spi_tfcr; /* Tx function code */
|
||||
ushort spi_mrblr; /* Max receive buffer length */
|
||||
uint spi_rstate; /* Internal */
|
||||
uint spi_rdp; /* Internal */
|
||||
ushort spi_rbptr; /* Internal */
|
||||
ushort spi_rbc; /* Internal */
|
||||
uint spi_rxtmp; /* Internal */
|
||||
uint spi_tstate; /* Internal */
|
||||
uint spi_tdp; /* Internal */
|
||||
ushort spi_tbptr; /* Internal */
|
||||
ushort spi_tbc; /* Internal */
|
||||
uint spi_txtmp; /* Internal */
|
||||
uint spi_res; /* Tx temp. */
|
||||
uint spi_res1[4]; /* SDMA temp. */
|
||||
} spi_t;
|
||||
|
||||
/* SPI Mode register.
|
||||
*/
|
||||
#define SPMODE_LOOP ((ushort)0x4000) /* Loopback */
|
||||
#define SPMODE_CI ((ushort)0x2000) /* Clock Invert */
|
||||
#define SPMODE_CP ((ushort)0x1000) /* Clock Phase */
|
||||
#define SPMODE_DIV16 ((ushort)0x0800) /* BRG/16 mode */
|
||||
#define SPMODE_REV ((ushort)0x0400) /* Reversed Data */
|
||||
#define SPMODE_MSTR ((ushort)0x0200) /* SPI Master */
|
||||
#define SPMODE_EN ((ushort)0x0100) /* Enable */
|
||||
#define SPMODE_LENMSK ((ushort)0x00f0) /* character length */
|
||||
#define SPMODE_PMMSK ((ushort)0x000f) /* prescale modulus */
|
||||
|
||||
#define SPMODE_LEN(x) ((((x)-1)&0xF)<<4)
|
||||
#define SPMODE_PM(x) ((x) &0xF)
|
||||
|
||||
#define SPI_EB ((u_char)0x10) /* big endian byte order */
|
||||
|
||||
/* IDMA parameter RAM
|
||||
*/
|
||||
typedef struct idma {
|
||||
|
|
|
@ -147,6 +147,7 @@
|
|||
.globl label##_pSeries; \
|
||||
label##_pSeries: \
|
||||
HMT_MEDIUM; \
|
||||
DO_KVM n; \
|
||||
mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \
|
||||
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
|
||||
|
||||
|
@ -170,6 +171,7 @@ label##_pSeries: \
|
|||
.globl label##_pSeries; \
|
||||
label##_pSeries: \
|
||||
HMT_MEDIUM; \
|
||||
DO_KVM n; \
|
||||
mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \
|
||||
mfspr r13,SPRN_SPRG_PACA; /* get paca address into r13 */ \
|
||||
std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
|
||||
#include <asm/page.h>
|
||||
|
||||
pte_t *huge_pte_offset_and_shift(struct mm_struct *mm,
|
||||
unsigned long addr, unsigned *shift);
|
||||
|
||||
void flush_dcache_icache_hugepage(struct page *page);
|
||||
|
||||
int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
|
||||
unsigned long len);
|
||||
|
@ -11,12 +15,6 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
|
|||
unsigned long end, unsigned long floor,
|
||||
unsigned long ceiling);
|
||||
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte);
|
||||
|
||||
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep);
|
||||
|
||||
/*
|
||||
* The version of vma_mmu_pagesize() in arch/powerpc/mm/hugetlbpage.c needs
|
||||
* to override the version in mm/hugetlb.c
|
||||
|
@ -42,9 +40,26 @@ static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm)
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte)
|
||||
{
|
||||
set_pte_at(mm, addr, ptep, pte);
|
||||
}
|
||||
|
||||
static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
unsigned long old = pte_update(mm, addr, ptep, ~0UL, 1);
|
||||
return __pte(old);
|
||||
}
|
||||
|
||||
static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
pte_t pte;
|
||||
pte = huge_ptep_get_and_clear(vma->vm_mm, addr, ptep);
|
||||
flush_tlb_page(vma, addr);
|
||||
}
|
||||
|
||||
static inline int huge_pte_none(pte_t pte)
|
||||
|
|
|
@ -212,6 +212,19 @@
|
|||
#define H_QUERY_INT_STATE 0x1E4
|
||||
#define H_POLL_PENDING 0x1D8
|
||||
#define H_ILLAN_ATTRIBUTES 0x244
|
||||
#define H_MODIFY_HEA_QP 0x250
|
||||
#define H_QUERY_HEA_QP 0x254
|
||||
#define H_QUERY_HEA 0x258
|
||||
#define H_QUERY_HEA_PORT 0x25C
|
||||
#define H_MODIFY_HEA_PORT 0x260
|
||||
#define H_REG_BCMC 0x264
|
||||
#define H_DEREG_BCMC 0x268
|
||||
#define H_REGISTER_HEA_RPAGES 0x26C
|
||||
#define H_DISABLE_AND_GET_HEA 0x270
|
||||
#define H_GET_HEA_INFO 0x274
|
||||
#define H_ALLOC_HEA_RESOURCE 0x278
|
||||
#define H_ADD_CONN 0x284
|
||||
#define H_DEL_CONN 0x288
|
||||
#define H_JOIN 0x298
|
||||
#define H_VASI_STATE 0x2A4
|
||||
#define H_ENABLE_CRQ 0x2B0
|
||||
|
|
|
@ -64,11 +64,6 @@ extern void iseries_handle_interrupts(void);
|
|||
get_paca()->hard_enabled = 0; \
|
||||
} while(0)
|
||||
|
||||
static inline int irqs_disabled_flags(unsigned long flags)
|
||||
{
|
||||
return flags == 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if defined(CONFIG_BOOKE)
|
||||
|
|
|
@ -549,7 +549,7 @@ typedef struct comm_proc {
|
|||
|
||||
/* USB Controller.
|
||||
*/
|
||||
typedef struct usb_ctlr {
|
||||
typedef struct cpm_usb_ctlr {
|
||||
u8 usb_usmod;
|
||||
u8 usb_usadr;
|
||||
u8 usb_uscom;
|
||||
|
|
|
@ -210,7 +210,7 @@ struct sir {
|
|||
} __attribute__ ((packed));
|
||||
|
||||
/* USB Controller */
|
||||
struct usb_ctlr {
|
||||
struct qe_usb_ctlr {
|
||||
u8 usb_usmod;
|
||||
u8 usb_usadr;
|
||||
u8 usb_uscom;
|
||||
|
@ -229,7 +229,7 @@ struct usb_ctlr {
|
|||
} __attribute__ ((packed));
|
||||
|
||||
/* MCC */
|
||||
struct mcc {
|
||||
struct qe_mcc {
|
||||
__be32 mcce; /* MCC event register */
|
||||
__be32 mccm; /* MCC mask register */
|
||||
__be32 mccf; /* MCC configuration register */
|
||||
|
@ -431,9 +431,9 @@ struct qe_immap {
|
|||
struct qe_mux qmx; /* QE Multiplexer */
|
||||
struct qe_timers qet; /* QE Timers */
|
||||
struct spi spi[0x2]; /* spi */
|
||||
struct mcc mcc; /* mcc */
|
||||
struct qe_mcc mcc; /* mcc */
|
||||
struct qe_brg brg; /* brg */
|
||||
struct usb_ctlr usb; /* USB */
|
||||
struct qe_usb_ctlr usb; /* USB */
|
||||
struct si1 si1; /* SI */
|
||||
u8 res11[0x800];
|
||||
struct sir sir; /* SI Routing Tables */
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
#include <asm/atomic.h>
|
||||
|
||||
|
||||
#define get_irq_desc(irq) (&irq_desc[(irq)])
|
||||
|
||||
/* Define a way to iterate across irqs. */
|
||||
#define for_each_irq(i) \
|
||||
for ((i) = 0; (i) < NR_IRQS; ++(i))
|
||||
|
@ -34,12 +32,15 @@ extern atomic_t ppc_n_lost_interrupts;
|
|||
*/
|
||||
#define NO_IRQ_IGNORE ((unsigned int)-1)
|
||||
|
||||
/* Total number of virq in the platform (make it a CONFIG_* option ? */
|
||||
#define NR_IRQS 512
|
||||
/* Total number of virq in the platform */
|
||||
#define NR_IRQS CONFIG_NR_IRQS
|
||||
|
||||
/* Number of irqs reserved for the legacy controller */
|
||||
#define NUM_ISA_INTERRUPTS 16
|
||||
|
||||
/* Same thing, used by the generic IRQ code */
|
||||
#define NR_IRQS_LEGACY NUM_ISA_INTERRUPTS
|
||||
|
||||
/* This type is the placeholder for a hardware interrupt number. It has to
|
||||
* be big enough to enclose whatever representation is used by a given
|
||||
* platform.
|
||||
|
@ -99,7 +100,7 @@ struct irq_host_ops {
|
|||
* interrupt controller has for that line)
|
||||
*/
|
||||
int (*xlate)(struct irq_host *h, struct device_node *ctrler,
|
||||
u32 *intspec, unsigned int intsize,
|
||||
const u32 *intspec, unsigned int intsize,
|
||||
irq_hw_number_t *out_hwirq, unsigned int *out_type);
|
||||
};
|
||||
|
||||
|
@ -313,7 +314,7 @@ extern void irq_free_virt(unsigned int virq, unsigned int count);
|
|||
* of the of_irq_map_*() functions.
|
||||
*/
|
||||
extern unsigned int irq_create_of_mapping(struct device_node *controller,
|
||||
u32 *intspec, unsigned int intsize);
|
||||
const u32 *intspec, unsigned int intsize);
|
||||
|
||||
/**
|
||||
* irq_of_parse_and_map - Parse and Map an interrupt into linux virq space
|
||||
|
|
|
@ -46,6 +46,24 @@ struct kvm_regs {
|
|||
};
|
||||
|
||||
struct kvm_sregs {
|
||||
__u32 pvr;
|
||||
union {
|
||||
struct {
|
||||
__u64 sdr1;
|
||||
struct {
|
||||
struct {
|
||||
__u64 slbe;
|
||||
__u64 slbv;
|
||||
} slb[64];
|
||||
} ppc64;
|
||||
struct {
|
||||
__u32 sr[16];
|
||||
__u64 ibat[8];
|
||||
__u64 dbat[8];
|
||||
} ppc32;
|
||||
} s;
|
||||
__u8 pad[1020];
|
||||
} u;
|
||||
};
|
||||
|
||||
struct kvm_fpu {
|
||||
|
|
|
@ -49,6 +49,46 @@
|
|||
#define BOOKE_INTERRUPT_SPE_FP_ROUND 34
|
||||
#define BOOKE_INTERRUPT_PERFORMANCE_MONITOR 35
|
||||
|
||||
/* book3s */
|
||||
|
||||
#define BOOK3S_INTERRUPT_SYSTEM_RESET 0x100
|
||||
#define BOOK3S_INTERRUPT_MACHINE_CHECK 0x200
|
||||
#define BOOK3S_INTERRUPT_DATA_STORAGE 0x300
|
||||
#define BOOK3S_INTERRUPT_DATA_SEGMENT 0x380
|
||||
#define BOOK3S_INTERRUPT_INST_STORAGE 0x400
|
||||
#define BOOK3S_INTERRUPT_INST_SEGMENT 0x480
|
||||
#define BOOK3S_INTERRUPT_EXTERNAL 0x500
|
||||
#define BOOK3S_INTERRUPT_ALIGNMENT 0x600
|
||||
#define BOOK3S_INTERRUPT_PROGRAM 0x700
|
||||
#define BOOK3S_INTERRUPT_FP_UNAVAIL 0x800
|
||||
#define BOOK3S_INTERRUPT_DECREMENTER 0x900
|
||||
#define BOOK3S_INTERRUPT_SYSCALL 0xc00
|
||||
#define BOOK3S_INTERRUPT_TRACE 0xd00
|
||||
#define BOOK3S_INTERRUPT_PERFMON 0xf00
|
||||
#define BOOK3S_INTERRUPT_ALTIVEC 0xf20
|
||||
#define BOOK3S_INTERRUPT_VSX 0xf40
|
||||
|
||||
#define BOOK3S_IRQPRIO_SYSTEM_RESET 0
|
||||
#define BOOK3S_IRQPRIO_DATA_SEGMENT 1
|
||||
#define BOOK3S_IRQPRIO_INST_SEGMENT 2
|
||||
#define BOOK3S_IRQPRIO_DATA_STORAGE 3
|
||||
#define BOOK3S_IRQPRIO_INST_STORAGE 4
|
||||
#define BOOK3S_IRQPRIO_ALIGNMENT 5
|
||||
#define BOOK3S_IRQPRIO_PROGRAM 6
|
||||
#define BOOK3S_IRQPRIO_FP_UNAVAIL 7
|
||||
#define BOOK3S_IRQPRIO_ALTIVEC 8
|
||||
#define BOOK3S_IRQPRIO_VSX 9
|
||||
#define BOOK3S_IRQPRIO_SYSCALL 10
|
||||
#define BOOK3S_IRQPRIO_MACHINE_CHECK 11
|
||||
#define BOOK3S_IRQPRIO_DEBUG 12
|
||||
#define BOOK3S_IRQPRIO_EXTERNAL 13
|
||||
#define BOOK3S_IRQPRIO_DECREMENTER 14
|
||||
#define BOOK3S_IRQPRIO_PERFORMANCE_MONITOR 15
|
||||
#define BOOK3S_IRQPRIO_MAX 16
|
||||
|
||||
#define BOOK3S_HFLAG_DCBZ32 0x1
|
||||
#define BOOK3S_HFLAG_SLB 0x2
|
||||
|
||||
#define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */
|
||||
#define RESUME_FLAG_HOST (1<<1) /* Resume host? */
|
||||
|
||||
|
|
139
arch/powerpc/include/asm/kvm_book3s.h
Normal file
139
arch/powerpc/include/asm/kvm_book3s.h
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright SUSE Linux Products GmbH 2009
|
||||
*
|
||||
* Authors: Alexander Graf <agraf@suse.de>
|
||||
*/
|
||||
|
||||
#ifndef __ASM_KVM_BOOK3S_H__
|
||||
#define __ASM_KVM_BOOK3S_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <asm/kvm_ppc.h>
|
||||
|
||||
struct kvmppc_slb {
|
||||
u64 esid;
|
||||
u64 vsid;
|
||||
u64 orige;
|
||||
u64 origv;
|
||||
bool valid;
|
||||
bool Ks;
|
||||
bool Kp;
|
||||
bool nx;
|
||||
bool large;
|
||||
bool class;
|
||||
};
|
||||
|
||||
struct kvmppc_sr {
|
||||
u32 raw;
|
||||
u32 vsid;
|
||||
bool Ks;
|
||||
bool Kp;
|
||||
bool nx;
|
||||
};
|
||||
|
||||
struct kvmppc_bat {
|
||||
u64 raw;
|
||||
u32 bepi;
|
||||
u32 bepi_mask;
|
||||
bool vs;
|
||||
bool vp;
|
||||
u32 brpn;
|
||||
u8 wimg;
|
||||
u8 pp;
|
||||
};
|
||||
|
||||
struct kvmppc_sid_map {
|
||||
u64 guest_vsid;
|
||||
u64 guest_esid;
|
||||
u64 host_vsid;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
#define SID_MAP_BITS 9
|
||||
#define SID_MAP_NUM (1 << SID_MAP_BITS)
|
||||
#define SID_MAP_MASK (SID_MAP_NUM - 1)
|
||||
|
||||
struct kvmppc_vcpu_book3s {
|
||||
struct kvm_vcpu vcpu;
|
||||
struct kvmppc_sid_map sid_map[SID_MAP_NUM];
|
||||
struct kvmppc_slb slb[64];
|
||||
struct {
|
||||
u64 esid;
|
||||
u64 vsid;
|
||||
} slb_shadow[64];
|
||||
u8 slb_shadow_max;
|
||||
struct kvmppc_sr sr[16];
|
||||
struct kvmppc_bat ibat[8];
|
||||
struct kvmppc_bat dbat[8];
|
||||
u64 hid[6];
|
||||
int slb_nr;
|
||||
u64 sdr1;
|
||||
u64 dsisr;
|
||||
u64 hior;
|
||||
u64 msr_mask;
|
||||
u64 vsid_first;
|
||||
u64 vsid_next;
|
||||
u64 vsid_max;
|
||||
int context_id;
|
||||
};
|
||||
|
||||
#define CONTEXT_HOST 0
|
||||
#define CONTEXT_GUEST 1
|
||||
#define CONTEXT_GUEST_END 2
|
||||
|
||||
#define VSID_REAL 0xfffffffffff00000
|
||||
#define VSID_REAL_DR 0xffffffffffe00000
|
||||
#define VSID_REAL_IR 0xffffffffffd00000
|
||||
#define VSID_BAT 0xffffffffffc00000
|
||||
#define VSID_PR 0x8000000000000000
|
||||
|
||||
extern void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, u64 ea, u64 ea_mask);
|
||||
extern void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 vp, u64 vp_mask);
|
||||
extern void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, u64 pa_start, u64 pa_end);
|
||||
extern void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 new_msr);
|
||||
extern void kvmppc_mmu_book3s_64_init(struct kvm_vcpu *vcpu);
|
||||
extern void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu);
|
||||
extern int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte);
|
||||
extern int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr);
|
||||
extern void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu);
|
||||
extern struct kvmppc_pte *kvmppc_mmu_find_pte(struct kvm_vcpu *vcpu, u64 ea, bool data);
|
||||
extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr, bool data);
|
||||
extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr);
|
||||
extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec);
|
||||
extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat,
|
||||
bool upper, u32 val);
|
||||
|
||||
extern u32 kvmppc_trampoline_lowmem;
|
||||
extern u32 kvmppc_trampoline_enter;
|
||||
|
||||
static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return container_of(vcpu, struct kvmppc_vcpu_book3s, vcpu);
|
||||
}
|
||||
|
||||
static inline ulong dsisr(void)
|
||||
{
|
||||
ulong r;
|
||||
asm ( "mfdsisr %0 " : "=r" (r) );
|
||||
return r;
|
||||
}
|
||||
|
||||
extern void kvm_return_point(void);
|
||||
|
||||
#define INS_DCBZ 0x7c0007ec
|
||||
|
||||
#endif /* __ASM_KVM_BOOK3S_H__ */
|
58
arch/powerpc/include/asm/kvm_book3s_64_asm.h
Normal file
58
arch/powerpc/include/asm/kvm_book3s_64_asm.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright SUSE Linux Products GmbH 2009
|
||||
*
|
||||
* Authors: Alexander Graf <agraf@suse.de>
|
||||
*/
|
||||
|
||||
#ifndef __ASM_KVM_BOOK3S_ASM_H__
|
||||
#define __ASM_KVM_BOOK3S_ASM_H__
|
||||
|
||||
#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
|
||||
|
||||
#include <asm/kvm_asm.h>
|
||||
|
||||
.macro DO_KVM intno
|
||||
.if (\intno == BOOK3S_INTERRUPT_SYSTEM_RESET) || \
|
||||
(\intno == BOOK3S_INTERRUPT_MACHINE_CHECK) || \
|
||||
(\intno == BOOK3S_INTERRUPT_DATA_STORAGE) || \
|
||||
(\intno == BOOK3S_INTERRUPT_INST_STORAGE) || \
|
||||
(\intno == BOOK3S_INTERRUPT_DATA_SEGMENT) || \
|
||||
(\intno == BOOK3S_INTERRUPT_INST_SEGMENT) || \
|
||||
(\intno == BOOK3S_INTERRUPT_EXTERNAL) || \
|
||||
(\intno == BOOK3S_INTERRUPT_ALIGNMENT) || \
|
||||
(\intno == BOOK3S_INTERRUPT_PROGRAM) || \
|
||||
(\intno == BOOK3S_INTERRUPT_FP_UNAVAIL) || \
|
||||
(\intno == BOOK3S_INTERRUPT_DECREMENTER) || \
|
||||
(\intno == BOOK3S_INTERRUPT_SYSCALL) || \
|
||||
(\intno == BOOK3S_INTERRUPT_TRACE) || \
|
||||
(\intno == BOOK3S_INTERRUPT_PERFMON) || \
|
||||
(\intno == BOOK3S_INTERRUPT_ALTIVEC) || \
|
||||
(\intno == BOOK3S_INTERRUPT_VSX)
|
||||
|
||||
b kvmppc_trampoline_\intno
|
||||
kvmppc_resume_\intno:
|
||||
|
||||
.endif
|
||||
.endm
|
||||
|
||||
#else
|
||||
|
||||
.macro DO_KVM intno
|
||||
.endm
|
||||
|
||||
#endif /* CONFIG_KVM_BOOK3S_64_HANDLER */
|
||||
|
||||
#endif /* __ASM_KVM_BOOK3S_ASM_H__ */
|
|
@ -21,7 +21,8 @@
|
|||
#define __POWERPC_KVM_HOST_H__
|
||||
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kvm_types.h>
|
||||
#include <asm/kvm_asm.h>
|
||||
|
@ -37,6 +38,8 @@
|
|||
#define KVM_NR_PAGE_SIZES 1
|
||||
#define KVM_PAGES_PER_HPAGE(x) (1UL<<31)
|
||||
|
||||
#define HPTEG_CACHE_NUM 1024
|
||||
|
||||
struct kvm;
|
||||
struct kvm_run;
|
||||
struct kvm_vcpu;
|
||||
|
@ -63,6 +66,17 @@ struct kvm_vcpu_stat {
|
|||
u32 dec_exits;
|
||||
u32 ext_intr_exits;
|
||||
u32 halt_wakeup;
|
||||
#ifdef CONFIG_PPC64
|
||||
u32 pf_storage;
|
||||
u32 pf_instruc;
|
||||
u32 sp_storage;
|
||||
u32 sp_instruc;
|
||||
u32 queue_intr;
|
||||
u32 ld;
|
||||
u32 ld_slow;
|
||||
u32 st;
|
||||
u32 st_slow;
|
||||
#endif
|
||||
};
|
||||
|
||||
enum kvm_exit_types {
|
||||
|
@ -109,9 +123,53 @@ struct kvmppc_exit_timing {
|
|||
struct kvm_arch {
|
||||
};
|
||||
|
||||
struct kvmppc_pte {
|
||||
u64 eaddr;
|
||||
u64 vpage;
|
||||
u64 raddr;
|
||||
bool may_read;
|
||||
bool may_write;
|
||||
bool may_execute;
|
||||
};
|
||||
|
||||
struct kvmppc_mmu {
|
||||
/* book3s_64 only */
|
||||
void (*slbmte)(struct kvm_vcpu *vcpu, u64 rb, u64 rs);
|
||||
u64 (*slbmfee)(struct kvm_vcpu *vcpu, u64 slb_nr);
|
||||
u64 (*slbmfev)(struct kvm_vcpu *vcpu, u64 slb_nr);
|
||||
void (*slbie)(struct kvm_vcpu *vcpu, u64 slb_nr);
|
||||
void (*slbia)(struct kvm_vcpu *vcpu);
|
||||
/* book3s */
|
||||
void (*mtsrin)(struct kvm_vcpu *vcpu, u32 srnum, ulong value);
|
||||
u32 (*mfsrin)(struct kvm_vcpu *vcpu, u32 srnum);
|
||||
int (*xlate)(struct kvm_vcpu *vcpu, gva_t eaddr, struct kvmppc_pte *pte, bool data);
|
||||
void (*reset_msr)(struct kvm_vcpu *vcpu);
|
||||
void (*tlbie)(struct kvm_vcpu *vcpu, ulong addr, bool large);
|
||||
int (*esid_to_vsid)(struct kvm_vcpu *vcpu, u64 esid, u64 *vsid);
|
||||
u64 (*ea_to_vp)(struct kvm_vcpu *vcpu, gva_t eaddr, bool data);
|
||||
bool (*is_dcbz32)(struct kvm_vcpu *vcpu);
|
||||
};
|
||||
|
||||
struct hpte_cache {
|
||||
u64 host_va;
|
||||
u64 pfn;
|
||||
ulong slot;
|
||||
struct kvmppc_pte pte;
|
||||
};
|
||||
|
||||
struct kvm_vcpu_arch {
|
||||
u32 host_stack;
|
||||
ulong host_stack;
|
||||
u32 host_pid;
|
||||
#ifdef CONFIG_PPC64
|
||||
ulong host_msr;
|
||||
ulong host_r2;
|
||||
void *host_retip;
|
||||
ulong trampoline_lowmem;
|
||||
ulong trampoline_enter;
|
||||
ulong highmem_handler;
|
||||
ulong host_paca_phys;
|
||||
struct kvmppc_mmu mmu;
|
||||
#endif
|
||||
|
||||
u64 fpr[32];
|
||||
ulong gpr[32];
|
||||
|
@ -123,6 +181,10 @@ struct kvm_vcpu_arch {
|
|||
ulong xer;
|
||||
|
||||
ulong msr;
|
||||
#ifdef CONFIG_PPC64
|
||||
ulong shadow_msr;
|
||||
ulong hflags;
|
||||
#endif
|
||||
u32 mmucr;
|
||||
ulong sprg0;
|
||||
ulong sprg1;
|
||||
|
@ -149,6 +211,7 @@ struct kvm_vcpu_arch {
|
|||
u32 ivor[64];
|
||||
ulong ivpr;
|
||||
u32 pir;
|
||||
u32 pvr;
|
||||
|
||||
u32 shadow_pid;
|
||||
u32 pid;
|
||||
|
@ -174,6 +237,9 @@ struct kvm_vcpu_arch {
|
|||
#endif
|
||||
|
||||
u32 last_inst;
|
||||
#ifdef CONFIG_PPC64
|
||||
ulong fault_dsisr;
|
||||
#endif
|
||||
ulong fault_dear;
|
||||
ulong fault_esr;
|
||||
gpa_t paddr_accessed;
|
||||
|
@ -185,8 +251,15 @@ struct kvm_vcpu_arch {
|
|||
|
||||
u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
|
||||
|
||||
struct timer_list dec_timer;
|
||||
struct hrtimer dec_timer;
|
||||
struct tasklet_struct tasklet;
|
||||
u64 dec_jiffies;
|
||||
unsigned long pending_exceptions;
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
struct hpte_cache hpte_cache[HPTEG_CACHE_NUM];
|
||||
int hpte_cache_offset;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* __POWERPC_KVM_HOST_H__ */
|
||||
|
|
|
@ -39,6 +39,7 @@ enum emulation_result {
|
|||
extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
|
||||
extern char kvmppc_handlers_start[];
|
||||
extern unsigned long kvmppc_handler_len;
|
||||
extern void kvmppc_handler_highmem(void);
|
||||
|
||||
extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu);
|
||||
extern int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||
|
|
|
@ -100,7 +100,14 @@ struct lppaca {
|
|||
// Used to pass parms from the OS to PLIC for SetAsrAndRfid
|
||||
u64 saved_gpr3; // Saved GPR3 x20-x27
|
||||
u64 saved_gpr4; // Saved GPR4 x28-x2F
|
||||
u64 saved_gpr5; // Saved GPR5 x30-x37
|
||||
union {
|
||||
u64 saved_gpr5; /* Saved GPR5 x30-x37 */
|
||||
struct {
|
||||
u8 cede_latency_hint; /* x30 */
|
||||
u8 reserved[7]; /* x31-x36 */
|
||||
} fields;
|
||||
} gpr5_dword;
|
||||
|
||||
|
||||
u8 dtl_enable_mask; // Dispatch Trace Log mask x38-x38
|
||||
u8 donate_dedicated_cpu; // Donate dedicated CPU cycles x39-x39
|
||||
|
|
|
@ -266,6 +266,11 @@ struct machdep_calls {
|
|||
void (*suspend_disable_irqs)(void);
|
||||
void (*suspend_enable_irqs)(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
|
||||
ssize_t (*cpu_probe)(const char *, size_t);
|
||||
ssize_t (*cpu_release)(const char *, size_t);
|
||||
#endif
|
||||
};
|
||||
|
||||
extern void e500_idle(void);
|
||||
|
|
|
@ -39,6 +39,7 @@ struct macio_dev
|
|||
struct macio_bus *bus; /* macio bus this device is on */
|
||||
struct macio_dev *media_bay; /* Device is part of a media bay */
|
||||
struct of_device ofdev;
|
||||
struct device_dma_parameters dma_parms; /* ide needs that */
|
||||
int n_resources;
|
||||
struct resource resource[MACIO_DEV_COUNT_RESOURCES];
|
||||
int n_interrupts;
|
||||
|
@ -78,6 +79,8 @@ static inline unsigned long macio_resource_len(struct macio_dev *dev, int resour
|
|||
return res->end - res->start + 1;
|
||||
}
|
||||
|
||||
extern int macio_enable_devres(struct macio_dev *dev);
|
||||
|
||||
extern int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name);
|
||||
extern void macio_release_resource(struct macio_dev *dev, int resource_no);
|
||||
extern int macio_request_resources(struct macio_dev *dev, const char *name);
|
||||
|
@ -131,6 +134,9 @@ struct macio_driver
|
|||
int (*resume)(struct macio_dev* dev);
|
||||
int (*shutdown)(struct macio_dev* dev);
|
||||
|
||||
#ifdef CONFIG_PMAC_MEDIABAY
|
||||
void (*mediabay_event)(struct macio_dev* dev, int mb_state);
|
||||
#endif
|
||||
struct device_driver driver;
|
||||
};
|
||||
#define to_macio_driver(drv) container_of(drv,struct macio_driver, driver)
|
||||
|
|
|
@ -17,26 +17,31 @@
|
|||
#define MB_POWER 6 /* media bay contains a Power device (???) */
|
||||
#define MB_NO 7 /* media bay contains nothing */
|
||||
|
||||
/* Number of bays in the machine or 0 */
|
||||
extern int media_bay_count;
|
||||
struct macio_dev;
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_IDE_PMAC
|
||||
#include <linux/ide.h>
|
||||
#ifdef CONFIG_PMAC_MEDIABAY
|
||||
|
||||
int check_media_bay_by_base(unsigned long base, int what);
|
||||
/* called by IDE PMAC host driver to register IDE controller for media bay */
|
||||
int media_bay_set_ide_infos(struct device_node *which_bay, unsigned long base,
|
||||
int irq, ide_hwif_t *hwif);
|
||||
/* Check the content type of the bay, returns MB_NO if the bay is still
|
||||
* transitionning
|
||||
*/
|
||||
extern int check_media_bay(struct macio_dev *bay);
|
||||
|
||||
int check_media_bay(struct device_node *which_bay, int what);
|
||||
/* The ATA driver uses the calls below to temporarily hold on the
|
||||
* media bay callbacks while initializing the interface
|
||||
*/
|
||||
extern void lock_media_bay(struct macio_dev *bay);
|
||||
extern void unlock_media_bay(struct macio_dev *bay);
|
||||
|
||||
#else
|
||||
|
||||
static inline int check_media_bay(struct device_node *which_bay, int what)
|
||||
static inline int check_media_bay(struct macio_dev *bay)
|
||||
{
|
||||
return -ENODEV;
|
||||
return MB_NO;
|
||||
}
|
||||
|
||||
static inline void lock_media_bay(struct macio_dev *bay) { }
|
||||
static inline void unlock_media_bay(struct macio_dev *bay) { }
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
|
|
@ -173,14 +173,6 @@ extern unsigned long tce_alloc_start, tce_alloc_end;
|
|||
*/
|
||||
extern int mmu_ci_restrictions;
|
||||
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
/*
|
||||
* The page size indexes of the huge pages for use by hugetlbfs
|
||||
*/
|
||||
extern unsigned int mmu_huge_psizes[MMU_PAGE_COUNT];
|
||||
|
||||
#endif /* CONFIG_HUGETLB_PAGE */
|
||||
|
||||
/*
|
||||
* This function sets the AVPN and L fields of the HPTE appropriately
|
||||
* for the page size
|
||||
|
@ -253,10 +245,11 @@ extern int __hash_page_64K(unsigned long ea, unsigned long access,
|
|||
unsigned long vsid, pte_t *ptep, unsigned long trap,
|
||||
unsigned int local, int ssize);
|
||||
struct mm_struct;
|
||||
unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap);
|
||||
extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap);
|
||||
extern int hash_huge_page(struct mm_struct *mm, unsigned long access,
|
||||
unsigned long ea, unsigned long vsid, int local,
|
||||
unsigned long trap);
|
||||
int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
|
||||
pte_t *ptep, unsigned long trap, int local, int ssize,
|
||||
unsigned int shift, unsigned int mmu_psize);
|
||||
|
||||
extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
|
||||
unsigned long pstart, unsigned long prot,
|
||||
|
@ -380,6 +373,38 @@ extern void slb_set_size(u16 size);
|
|||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#ifdef CONFIG_PPC_SUBPAGE_PROT
|
||||
/*
|
||||
* For the sub-page protection option, we extend the PGD with one of
|
||||
* these. Basically we have a 3-level tree, with the top level being
|
||||
* the protptrs array. To optimize speed and memory consumption when
|
||||
* only addresses < 4GB are being protected, pointers to the first
|
||||
* four pages of sub-page protection words are stored in the low_prot
|
||||
* array.
|
||||
* Each page of sub-page protection words protects 1GB (4 bytes
|
||||
* protects 64k). For the 3-level tree, each page of pointers then
|
||||
* protects 8TB.
|
||||
*/
|
||||
struct subpage_prot_table {
|
||||
unsigned long maxaddr; /* only addresses < this are protected */
|
||||
unsigned int **protptrs[2];
|
||||
unsigned int *low_prot[4];
|
||||
};
|
||||
|
||||
#define SBP_L1_BITS (PAGE_SHIFT - 2)
|
||||
#define SBP_L2_BITS (PAGE_SHIFT - 3)
|
||||
#define SBP_L1_COUNT (1 << SBP_L1_BITS)
|
||||
#define SBP_L2_COUNT (1 << SBP_L2_BITS)
|
||||
#define SBP_L2_SHIFT (PAGE_SHIFT + SBP_L1_BITS)
|
||||
#define SBP_L3_SHIFT (SBP_L2_SHIFT + SBP_L2_BITS)
|
||||
|
||||
extern void subpage_prot_free(struct mm_struct *mm);
|
||||
extern void subpage_prot_init_new_context(struct mm_struct *mm);
|
||||
#else
|
||||
static inline void subpage_prot_free(struct mm_struct *mm) {}
|
||||
static inline void subpage_prot_init_new_context(struct mm_struct *mm) { }
|
||||
#endif /* CONFIG_PPC_SUBPAGE_PROT */
|
||||
|
||||
typedef unsigned long mm_context_id_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -393,6 +418,9 @@ typedef struct {
|
|||
u16 sllp; /* SLB page size encoding */
|
||||
#endif
|
||||
unsigned long vdso_base;
|
||||
#ifdef CONFIG_PPC_SUBPAGE_PROT
|
||||
struct subpage_prot_table spt;
|
||||
#endif /* CONFIG_PPC_SUBPAGE_PROT */
|
||||
} mm_context_t;
|
||||
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm);
|
|||
extern void set_context(unsigned long id, pgd_t *pgd);
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
extern int __init_new_context(void);
|
||||
extern void __destroy_context(int context_id);
|
||||
static inline void mmu_context_init(void) { }
|
||||
#else
|
||||
extern void mmu_context_init(void);
|
||||
|
|
|
@ -276,6 +276,53 @@ extern int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv);
|
|||
extern unsigned int mpc52xx_get_xtal_freq(struct device_node *node);
|
||||
extern void mpc52xx_restart(char *cmd);
|
||||
|
||||
/* mpc52xx_gpt.c */
|
||||
struct mpc52xx_gpt_priv;
|
||||
extern struct mpc52xx_gpt_priv *mpc52xx_gpt_from_irq(int irq);
|
||||
extern int mpc52xx_gpt_start_timer(struct mpc52xx_gpt_priv *gpt, u64 period,
|
||||
int continuous);
|
||||
extern u64 mpc52xx_gpt_timer_period(struct mpc52xx_gpt_priv *gpt);
|
||||
extern int mpc52xx_gpt_stop_timer(struct mpc52xx_gpt_priv *gpt);
|
||||
|
||||
/* mpc52xx_lpbfifo.c */
|
||||
#define MPC52XX_LPBFIFO_FLAG_READ (0)
|
||||
#define MPC52XX_LPBFIFO_FLAG_WRITE (1<<0)
|
||||
#define MPC52XX_LPBFIFO_FLAG_NO_INCREMENT (1<<1)
|
||||
#define MPC52XX_LPBFIFO_FLAG_NO_DMA (1<<2)
|
||||
#define MPC52XX_LPBFIFO_FLAG_POLL_DMA (1<<3)
|
||||
|
||||
struct mpc52xx_lpbfifo_request {
|
||||
struct list_head list;
|
||||
|
||||
/* localplus bus address */
|
||||
unsigned int cs;
|
||||
size_t offset;
|
||||
|
||||
/* Memory address */
|
||||
void *data;
|
||||
phys_addr_t data_phys;
|
||||
|
||||
/* Details of transfer */
|
||||
size_t size;
|
||||
size_t pos; /* current position of transfer */
|
||||
int flags;
|
||||
|
||||
/* What to do when finished */
|
||||
void (*callback)(struct mpc52xx_lpbfifo_request *);
|
||||
|
||||
void *priv; /* Driver private data */
|
||||
|
||||
/* statistics */
|
||||
int irq_count;
|
||||
int irq_ticks;
|
||||
u8 last_byte;
|
||||
int buffer_not_done_cnt;
|
||||
};
|
||||
|
||||
extern int mpc52xx_lpbfifo_submit(struct mpc52xx_lpbfifo_request *req);
|
||||
extern void mpc52xx_lpbfifo_abort(struct mpc52xx_lpbfifo_request *req);
|
||||
extern void mpc52xx_lpbfifo_poll(void);
|
||||
|
||||
/* mpc52xx_pic.c */
|
||||
extern void mpc52xx_init_irq(void);
|
||||
extern unsigned int mpc52xx_get_irq(void);
|
||||
|
|
|
@ -73,7 +73,6 @@ extern int nvram_write_error_log(char * buff, int length,
|
|||
extern int nvram_read_error_log(char * buff, int length,
|
||||
unsigned int * err_type, unsigned int *err_seq);
|
||||
extern int nvram_clear_error_log(void);
|
||||
extern struct nvram_partition *nvram_find_partition(int sig, const char *name);
|
||||
|
||||
extern int pSeries_nvram_init(void);
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#ifdef CONFIG_PPC_PSERIES
|
||||
extern int pSeries_reconfig_notifier_register(struct notifier_block *);
|
||||
extern void pSeries_reconfig_notifier_unregister(struct notifier_block *);
|
||||
extern struct blocking_notifier_head pSeries_reconfig_chain;
|
||||
#else /* !CONFIG_PPC_PSERIES */
|
||||
static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb)
|
||||
{
|
||||
|
|
|
@ -129,6 +129,15 @@ struct paca_struct {
|
|||
u64 system_time; /* accumulated system TB ticks */
|
||||
u64 startpurr; /* PURR/TB value snapshot */
|
||||
u64 startspurr; /* SPURR value snapshot */
|
||||
|
||||
#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
|
||||
struct {
|
||||
u64 esid;
|
||||
u64 vsid;
|
||||
} kvm_slb[64]; /* guest SLB */
|
||||
u8 kvm_slb_max; /* highest used guest slb entry */
|
||||
u8 kvm_in_guest; /* are we inside the guest? */
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct paca_struct paca[];
|
||||
|
|
|
@ -229,6 +229,20 @@ typedef unsigned long pgprot_t;
|
|||
|
||||
#endif
|
||||
|
||||
typedef struct { signed long pd; } hugepd_t;
|
||||
#define HUGEPD_SHIFT_MASK 0x3f
|
||||
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
static inline int hugepd_ok(hugepd_t hpd)
|
||||
{
|
||||
return (hpd.pd > 0);
|
||||
}
|
||||
|
||||
#define is_hugepd(pdep) (hugepd_ok(*((hugepd_t *)(pdep))))
|
||||
#else /* CONFIG_HUGETLB_PAGE */
|
||||
#define is_hugepd(pdep) 0
|
||||
#endif /* CONFIG_HUGETLB_PAGE */
|
||||
|
||||
struct page;
|
||||
extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg);
|
||||
extern void copy_user_page(void *to, void *from, unsigned long vaddr,
|
||||
|
|
|
@ -90,7 +90,7 @@ extern unsigned int HPAGE_SHIFT;
|
|||
#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT)
|
||||
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
|
||||
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
|
||||
#define HUGE_MAX_HSTATE 3
|
||||
#define HUGE_MAX_HSTATE (MMU_PAGE_COUNT-1)
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
#include <linux/threads.h>
|
||||
|
||||
#define PTE_NONCACHE_NUM 0 /* dummy for now to share code w/ppc64 */
|
||||
/* For 32-bit, all levels of page tables are just drawn from get_free_page() */
|
||||
#define MAX_PGTABLE_INDEX_SIZE 0
|
||||
|
||||
extern void __bad_pte(pmd_t *pmd);
|
||||
|
||||
|
@ -36,11 +37,10 @@ extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
|
|||
extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
|
||||
extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr);
|
||||
|
||||
static inline void pgtable_free(pgtable_free_t pgf)
|
||||
static inline void pgtable_free(void *table, unsigned index_size)
|
||||
{
|
||||
void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK);
|
||||
|
||||
free_page((unsigned long)p);
|
||||
BUG_ON(index_size); /* 32-bit doesn't use this */
|
||||
free_page((unsigned long)table);
|
||||
}
|
||||
|
||||
#define check_pgt_cache() do { } while (0)
|
||||
|
|
|
@ -11,27 +11,34 @@
|
|||
#include <linux/cpumask.h>
|
||||
#include <linux/percpu.h>
|
||||
|
||||
#ifndef CONFIG_PPC_SUBPAGE_PROT
|
||||
static inline void subpage_prot_free(pgd_t *pgd) {}
|
||||
#endif
|
||||
/*
|
||||
* Functions that deal with pagetables that could be at any level of
|
||||
* the table need to be passed an "index_size" so they know how to
|
||||
* handle allocation. For PTE pages (which are linked to a struct
|
||||
* page for now, and drawn from the main get_free_pages() pool), the
|
||||
* allocation size will be (2^index_size * sizeof(pointer)) and
|
||||
* allocations are drawn from the kmem_cache in PGT_CACHE(index_size).
|
||||
*
|
||||
* The maximum index size needs to be big enough to allow any
|
||||
* pagetable sizes we need, but small enough to fit in the low bits of
|
||||
* any page table pointer. In other words all pagetables, even tiny
|
||||
* ones, must be aligned to allow at least enough low 0 bits to
|
||||
* contain this value. This value is also used as a mask, so it must
|
||||
* be one less than a power of two.
|
||||
*/
|
||||
#define MAX_PGTABLE_INDEX_SIZE 0xf
|
||||
|
||||
extern struct kmem_cache *pgtable_cache[];
|
||||
|
||||
#define PGD_CACHE_NUM 0
|
||||
#define PUD_CACHE_NUM 1
|
||||
#define PMD_CACHE_NUM 1
|
||||
#define HUGEPTE_CACHE_NUM 2
|
||||
#define PTE_NONCACHE_NUM 7 /* from GFP rather than kmem_cache */
|
||||
#define PGT_CACHE(shift) (pgtable_cache[(shift)-1])
|
||||
|
||||
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
|
||||
{
|
||||
return kmem_cache_alloc(pgtable_cache[PGD_CACHE_NUM], GFP_KERNEL);
|
||||
return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), GFP_KERNEL);
|
||||
}
|
||||
|
||||
static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
||||
{
|
||||
subpage_prot_free(pgd);
|
||||
kmem_cache_free(pgtable_cache[PGD_CACHE_NUM], pgd);
|
||||
kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PPC_64K_PAGES
|
||||
|
@ -40,13 +47,13 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
|||
|
||||
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
|
||||
{
|
||||
return kmem_cache_alloc(pgtable_cache[PUD_CACHE_NUM],
|
||||
return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE),
|
||||
GFP_KERNEL|__GFP_REPEAT);
|
||||
}
|
||||
|
||||
static inline void pud_free(struct mm_struct *mm, pud_t *pud)
|
||||
{
|
||||
kmem_cache_free(pgtable_cache[PUD_CACHE_NUM], pud);
|
||||
kmem_cache_free(PGT_CACHE(PUD_INDEX_SIZE), pud);
|
||||
}
|
||||
|
||||
static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
|
||||
|
@ -78,13 +85,13 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
|
|||
|
||||
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
|
||||
{
|
||||
return kmem_cache_alloc(pgtable_cache[PMD_CACHE_NUM],
|
||||
return kmem_cache_alloc(PGT_CACHE(PMD_INDEX_SIZE),
|
||||
GFP_KERNEL|__GFP_REPEAT);
|
||||
}
|
||||
|
||||
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
|
||||
{
|
||||
kmem_cache_free(pgtable_cache[PMD_CACHE_NUM], pmd);
|
||||
kmem_cache_free(PGT_CACHE(PMD_INDEX_SIZE), pmd);
|
||||
}
|
||||
|
||||
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
||||
|
@ -107,24 +114,22 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
|
|||
return page;
|
||||
}
|
||||
|
||||
static inline void pgtable_free(pgtable_free_t pgf)
|
||||
static inline void pgtable_free(void *table, unsigned index_size)
|
||||
{
|
||||
void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK);
|
||||
int cachenum = pgf.val & PGF_CACHENUM_MASK;
|
||||
|
||||
if (cachenum == PTE_NONCACHE_NUM)
|
||||
free_page((unsigned long)p);
|
||||
else
|
||||
kmem_cache_free(pgtable_cache[cachenum], p);
|
||||
if (!index_size)
|
||||
free_page((unsigned long)table);
|
||||
else {
|
||||
BUG_ON(index_size > MAX_PGTABLE_INDEX_SIZE);
|
||||
kmem_cache_free(PGT_CACHE(index_size), table);
|
||||
}
|
||||
}
|
||||
|
||||
#define __pmd_free_tlb(tlb, pmd,addr) \
|
||||
pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \
|
||||
PMD_CACHE_NUM, PMD_TABLE_SIZE-1))
|
||||
#define __pmd_free_tlb(tlb, pmd, addr) \
|
||||
pgtable_free_tlb(tlb, pmd, PMD_INDEX_SIZE)
|
||||
#ifndef CONFIG_PPC_64K_PAGES
|
||||
#define __pud_free_tlb(tlb, pud, addr) \
|
||||
pgtable_free_tlb(tlb, pgtable_free_cache(pud, \
|
||||
PUD_CACHE_NUM, PUD_TABLE_SIZE-1))
|
||||
pgtable_free_tlb(tlb, pud, PUD_INDEX_SIZE)
|
||||
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
|
||||
#define check_pgt_cache() do { } while (0)
|
||||
|
|
|
@ -24,25 +24,6 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
|
|||
__free_page(ptepage);
|
||||
}
|
||||
|
||||
typedef struct pgtable_free {
|
||||
unsigned long val;
|
||||
} pgtable_free_t;
|
||||
|
||||
/* This needs to be big enough to allow for MMU_PAGE_COUNT + 2 to be stored
|
||||
* and small enough to fit in the low bits of any naturally aligned page
|
||||
* table cache entry. Arbitrarily set to 0x1f, that should give us some
|
||||
* room to grow
|
||||
*/
|
||||
#define PGF_CACHENUM_MASK 0x1f
|
||||
|
||||
static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum,
|
||||
unsigned long mask)
|
||||
{
|
||||
BUG_ON(cachenum > PGF_CACHENUM_MASK);
|
||||
|
||||
return (pgtable_free_t){.val = ((unsigned long) p & ~mask) | cachenum};
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#include <asm/pgalloc-64.h>
|
||||
#else
|
||||
|
@ -50,12 +31,12 @@ static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum,
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf);
|
||||
extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift);
|
||||
extern void pte_free_finish(void);
|
||||
#else /* CONFIG_SMP */
|
||||
static inline void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf)
|
||||
static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift)
|
||||
{
|
||||
pgtable_free(pgf);
|
||||
pgtable_free(table, shift);
|
||||
}
|
||||
static inline void pte_free_finish(void) { }
|
||||
#endif /* !CONFIG_SMP */
|
||||
|
@ -63,12 +44,9 @@ static inline void pte_free_finish(void) { }
|
|||
static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage,
|
||||
unsigned long address)
|
||||
{
|
||||
pgtable_free_t pgf = pgtable_free_cache(page_address(ptepage),
|
||||
PTE_NONCACHE_NUM,
|
||||
PTE_TABLE_SIZE-1);
|
||||
tlb_flush_pgtable(tlb, address);
|
||||
pgtable_page_dtor(ptepage);
|
||||
pgtable_free_tlb(tlb, pgf);
|
||||
pgtable_free_tlb(tlb, page_address(ptepage), 0);
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
|
|
@ -354,6 +354,7 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry)
|
|||
#define pgoff_to_pte(off) ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE})
|
||||
#define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_RPN_SHIFT)
|
||||
|
||||
void pgtable_cache_add(unsigned shift, void (*ctor)(void *));
|
||||
void pgtable_cache_init(void);
|
||||
|
||||
/*
|
||||
|
@ -378,7 +379,18 @@ void pgtable_cache_init(void);
|
|||
return pt;
|
||||
}
|
||||
|
||||
pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long address);
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
|
||||
unsigned *shift);
|
||||
#else
|
||||
static inline pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
|
||||
unsigned *shift)
|
||||
{
|
||||
if (shift)
|
||||
*shift = 0;
|
||||
return find_linux_pte(pgdir, ea);
|
||||
}
|
||||
#endif /* !CONFIG_HUGETLB_PAGE */
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
|
|
|
@ -211,6 +211,9 @@ extern void paging_init(void);
|
|||
*/
|
||||
extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
|
||||
|
||||
extern int gup_hugepd(hugepd_t *hugepd, unsigned pdshift, unsigned long addr,
|
||||
unsigned long end, int write, struct page **pages, int *nr);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
|
|
@ -33,21 +33,21 @@
|
|||
#define _PAGE_NO_CACHE 0x0002 /* I: cache inhibit */
|
||||
#define _PAGE_SHARED 0x0004 /* No ASID (context) compare */
|
||||
#define _PAGE_SPECIAL 0x0008 /* SW entry, forced to 0 by the TLB miss */
|
||||
#define _PAGE_DIRTY 0x0100 /* C: page changed */
|
||||
|
||||
/* These five software bits must be masked out when the entry is loaded
|
||||
* into the TLB.
|
||||
/* These 4 software bits must be masked out when the entry is loaded
|
||||
* into the TLB, 1 SW bit left(0x0080).
|
||||
*/
|
||||
#define _PAGE_GUARDED 0x0010 /* software: guarded access */
|
||||
#define _PAGE_DIRTY 0x0020 /* software: page changed */
|
||||
#define _PAGE_RW 0x0040 /* software: user write access allowed */
|
||||
#define _PAGE_ACCESSED 0x0080 /* software: page referenced */
|
||||
#define _PAGE_ACCESSED 0x0020 /* software: page referenced */
|
||||
#define _PAGE_WRITETHRU 0x0040 /* software: caching is write through */
|
||||
|
||||
/* Setting any bits in the nibble with the follow two controls will
|
||||
* require a TLB exception handler change. It is assumed unused bits
|
||||
* are always zero.
|
||||
*/
|
||||
#define _PAGE_HWWRITE 0x0100 /* h/w write enable: never set in Linux PTE */
|
||||
#define _PAGE_USER 0x0800 /* One of the PP bits, the other is USER&~RW */
|
||||
#define _PAGE_RW 0x0400 /* lsb PP bits, inverted in HW */
|
||||
#define _PAGE_USER 0x0800 /* msb PP bits */
|
||||
|
||||
#define _PMD_PRESENT 0x0001
|
||||
#define _PMD_BAD 0x0ff0
|
||||
|
|
|
@ -76,41 +76,4 @@
|
|||
remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, \
|
||||
__pgprot(pgprot_val((prot)) | _PAGE_4K_PFN))
|
||||
|
||||
|
||||
#ifdef CONFIG_PPC_SUBPAGE_PROT
|
||||
/*
|
||||
* For the sub-page protection option, we extend the PGD with one of
|
||||
* these. Basically we have a 3-level tree, with the top level being
|
||||
* the protptrs array. To optimize speed and memory consumption when
|
||||
* only addresses < 4GB are being protected, pointers to the first
|
||||
* four pages of sub-page protection words are stored in the low_prot
|
||||
* array.
|
||||
* Each page of sub-page protection words protects 1GB (4 bytes
|
||||
* protects 64k). For the 3-level tree, each page of pointers then
|
||||
* protects 8TB.
|
||||
*/
|
||||
struct subpage_prot_table {
|
||||
unsigned long maxaddr; /* only addresses < this are protected */
|
||||
unsigned int **protptrs[2];
|
||||
unsigned int *low_prot[4];
|
||||
};
|
||||
|
||||
#undef PGD_TABLE_SIZE
|
||||
#define PGD_TABLE_SIZE ((sizeof(pgd_t) << PGD_INDEX_SIZE) + \
|
||||
sizeof(struct subpage_prot_table))
|
||||
|
||||
#define SBP_L1_BITS (PAGE_SHIFT - 2)
|
||||
#define SBP_L2_BITS (PAGE_SHIFT - 3)
|
||||
#define SBP_L1_COUNT (1 << SBP_L1_BITS)
|
||||
#define SBP_L2_COUNT (1 << SBP_L2_BITS)
|
||||
#define SBP_L2_SHIFT (PAGE_SHIFT + SBP_L1_BITS)
|
||||
#define SBP_L3_SHIFT (SBP_L2_SHIFT + SBP_L2_BITS)
|
||||
|
||||
extern void subpage_prot_free(pgd_t *pgd);
|
||||
|
||||
static inline struct subpage_prot_table *pgd_subpage_prot(pgd_t *pgd)
|
||||
{
|
||||
return (struct subpage_prot_table *)(pgd + PTRS_PER_PGD);
|
||||
}
|
||||
#endif /* CONFIG_PPC_SUBPAGE_PROT */
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
|
|
@ -87,7 +87,7 @@ extern spinlock_t cmxgcr_lock;
|
|||
|
||||
/* Export QE common operations */
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
extern void __init qe_reset(void);
|
||||
extern void qe_reset(void);
|
||||
#else
|
||||
static inline void qe_reset(void) {}
|
||||
#endif
|
||||
|
@ -145,8 +145,17 @@ static inline void qe_pin_set_gpio(struct qe_pin *qe_pin) {}
|
|||
static inline void qe_pin_set_dedicated(struct qe_pin *pin) {}
|
||||
#endif /* CONFIG_QE_GPIO */
|
||||
|
||||
/* QE internal API */
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
|
||||
#else
|
||||
static inline int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol,
|
||||
u32 cmd_input)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
|
||||
/* QE internal API */
|
||||
enum qe_clock qe_clock_source(const char *source);
|
||||
unsigned int qe_get_brg_clk(void);
|
||||
int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
|
||||
|
@ -154,7 +163,28 @@ int qe_get_snum(void);
|
|||
void qe_put_snum(u8 snum);
|
||||
unsigned int qe_get_num_of_risc(void);
|
||||
unsigned int qe_get_num_of_snums(void);
|
||||
int qe_alive_during_sleep(void);
|
||||
|
||||
static inline int qe_alive_during_sleep(void)
|
||||
{
|
||||
/*
|
||||
* MPC8568E reference manual says:
|
||||
*
|
||||
* "...power down sequence waits for all I/O interfaces to become idle.
|
||||
* In some applications this may happen eventually without actively
|
||||
* shutting down interfaces, but most likely, software will have to
|
||||
* take steps to shut down the eTSEC, QUICC Engine Block, and PCI
|
||||
* interfaces before issuing the command (either the write to the core
|
||||
* MSR[WE] as described above or writing to POWMGTCSR) to put the
|
||||
* device into sleep state."
|
||||
*
|
||||
* MPC8569E reference manual has a similar paragraph.
|
||||
*/
|
||||
#ifdef CONFIG_PPC_85xx
|
||||
return 0;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* we actually use cpm_muram implementation, define this for convenience */
|
||||
#define qe_muram_init cpm_muram_init
|
||||
|
@ -210,8 +240,15 @@ struct qe_firmware_info {
|
|||
u64 extended_modes; /* Extended modes */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
/* Upload a firmware to the QE */
|
||||
int qe_upload_firmware(const struct qe_firmware *firmware);
|
||||
#else
|
||||
static inline int qe_upload_firmware(const struct qe_firmware *firmware)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
|
||||
/* Obtain information on the uploaded firmware */
|
||||
struct qe_firmware_info *qe_get_firmware_info(void);
|
||||
|
|
|
@ -145,7 +145,7 @@ SYSCALL_SPU(setfsuid)
|
|||
SYSCALL_SPU(setfsgid)
|
||||
SYSCALL_SPU(llseek)
|
||||
COMPAT_SYS_SPU(getdents)
|
||||
SYSX_SPU(sys_select,ppc32_select,ppc_select)
|
||||
SYSX_SPU(sys_select,ppc32_select,sys_select)
|
||||
SYSCALL_SPU(flock)
|
||||
SYSCALL_SPU(msync)
|
||||
COMPAT_SYS_SPU(readv)
|
||||
|
|
|
@ -42,10 +42,11 @@ obj-$(CONFIG_ALTIVEC) += vecemu.o
|
|||
obj-$(CONFIG_PPC_970_NAP) += idle_power4.o
|
||||
obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o
|
||||
obj-$(CONFIG_PPC_CLOCK) += clock.o
|
||||
procfs-$(CONFIG_PPC64) := proc_ppc64.o
|
||||
procfs-y := proc_powerpc.o
|
||||
obj-$(CONFIG_PROC_FS) += $(procfs-y)
|
||||
rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o
|
||||
obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y)
|
||||
obj-$(CONFIG_PPC_RTAS_DAEMON) += rtasd.o
|
||||
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
|
||||
obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
|
||||
obj-$(CONFIG_LPARCFG) += lparcfg.o
|
||||
|
|
|
@ -190,6 +190,11 @@ int main(void)
|
|||
DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
|
||||
DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset));
|
||||
DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
|
||||
#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
|
||||
DEFINE(PACA_KVM_IN_GUEST, offsetof(struct paca_struct, kvm_in_guest));
|
||||
DEFINE(PACA_KVM_SLB, offsetof(struct paca_struct, kvm_slb));
|
||||
DEFINE(PACA_KVM_SLB_MAX, offsetof(struct paca_struct, kvm_slb_max));
|
||||
#endif
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
/* RTAS */
|
||||
|
@ -398,14 +403,24 @@ int main(void)
|
|||
DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
|
||||
DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear));
|
||||
DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));
|
||||
|
||||
/* book3s_64 */
|
||||
#ifdef CONFIG_PPC64
|
||||
DEFINE(VCPU_FAULT_DSISR, offsetof(struct kvm_vcpu, arch.fault_dsisr));
|
||||
DEFINE(VCPU_HOST_RETIP, offsetof(struct kvm_vcpu, arch.host_retip));
|
||||
DEFINE(VCPU_HOST_R2, offsetof(struct kvm_vcpu, arch.host_r2));
|
||||
DEFINE(VCPU_HOST_MSR, offsetof(struct kvm_vcpu, arch.host_msr));
|
||||
DEFINE(VCPU_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_msr));
|
||||
DEFINE(VCPU_TRAMPOLINE_LOWMEM, offsetof(struct kvm_vcpu, arch.trampoline_lowmem));
|
||||
DEFINE(VCPU_TRAMPOLINE_ENTER, offsetof(struct kvm_vcpu, arch.trampoline_enter));
|
||||
DEFINE(VCPU_HIGHMEM_HANDLER, offsetof(struct kvm_vcpu, arch.highmem_handler));
|
||||
DEFINE(VCPU_HFLAGS, offsetof(struct kvm_vcpu, arch.hflags));
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_44x
|
||||
DEFINE(PGD_T_LOG2, PGD_T_LOG2);
|
||||
DEFINE(PTE_T_LOG2, PTE_T_LOG2);
|
||||
#endif
|
||||
#ifdef CONFIG_FSL_BOOKE
|
||||
DEFINE(TLBCAM_SIZE, sizeof(struct tlbcam));
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KVM_EXIT_TIMING
|
||||
DEFINE(VCPU_TIMING_EXIT_TBU, offsetof(struct kvm_vcpu,
|
||||
|
|
|
@ -373,7 +373,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
|
|||
hard_irq_disable();
|
||||
|
||||
for_each_irq(i) {
|
||||
struct irq_desc *desc = irq_desc + i;
|
||||
struct irq_desc *desc = irq_to_desc(i);
|
||||
|
||||
if (desc->status & IRQ_INPROGRESS)
|
||||
desc->chip->eoi(i);
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <asm/dma.h>
|
||||
#include <asm/abs_addr.h>
|
||||
|
||||
int swiotlb __read_mostly;
|
||||
unsigned int ppc_swiotlb_enable;
|
||||
|
||||
/*
|
||||
|
|
|
@ -41,6 +41,7 @@ __start_interrupts:
|
|||
. = 0x200
|
||||
_machine_check_pSeries:
|
||||
HMT_MEDIUM
|
||||
DO_KVM 0x200
|
||||
mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */
|
||||
EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
|
||||
|
||||
|
@ -48,6 +49,7 @@ _machine_check_pSeries:
|
|||
.globl data_access_pSeries
|
||||
data_access_pSeries:
|
||||
HMT_MEDIUM
|
||||
DO_KVM 0x300
|
||||
mtspr SPRN_SPRG_SCRATCH0,r13
|
||||
BEGIN_FTR_SECTION
|
||||
mfspr r13,SPRN_SPRG_PACA
|
||||
|
@ -77,6 +79,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_SLB)
|
|||
.globl data_access_slb_pSeries
|
||||
data_access_slb_pSeries:
|
||||
HMT_MEDIUM
|
||||
DO_KVM 0x380
|
||||
mtspr SPRN_SPRG_SCRATCH0,r13
|
||||
mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */
|
||||
std r3,PACA_EXSLB+EX_R3(r13)
|
||||
|
@ -115,6 +118,7 @@ data_access_slb_pSeries:
|
|||
.globl instruction_access_slb_pSeries
|
||||
instruction_access_slb_pSeries:
|
||||
HMT_MEDIUM
|
||||
DO_KVM 0x480
|
||||
mtspr SPRN_SPRG_SCRATCH0,r13
|
||||
mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */
|
||||
std r3,PACA_EXSLB+EX_R3(r13)
|
||||
|
@ -154,6 +158,7 @@ instruction_access_slb_pSeries:
|
|||
.globl system_call_pSeries
|
||||
system_call_pSeries:
|
||||
HMT_MEDIUM
|
||||
DO_KVM 0xc00
|
||||
BEGIN_FTR_SECTION
|
||||
cmpdi r0,0x1ebe
|
||||
beq- 1f
|
||||
|
@ -187,14 +192,17 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
|
|||
*/
|
||||
performance_monitor_pSeries_1:
|
||||
. = 0xf00
|
||||
DO_KVM 0xf00
|
||||
b performance_monitor_pSeries
|
||||
|
||||
altivec_unavailable_pSeries_1:
|
||||
. = 0xf20
|
||||
DO_KVM 0xf20
|
||||
b altivec_unavailable_pSeries
|
||||
|
||||
vsx_unavailable_pSeries_1:
|
||||
. = 0xf40
|
||||
DO_KVM 0xf40
|
||||
b vsx_unavailable_pSeries
|
||||
|
||||
#ifdef CONFIG_CBE_RAS
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <asm/firmware.h>
|
||||
#include <asm/page_64.h>
|
||||
#include <asm/irqflags.h>
|
||||
#include <asm/kvm_book3s_64_asm.h>
|
||||
|
||||
/* The physical memory is layed out such that the secondary processor
|
||||
* spin code sits at 0x0000...0x00ff. On server, the vectors follow
|
||||
|
@ -165,6 +166,12 @@ exception_marker:
|
|||
#include "exceptions-64s.S"
|
||||
#endif
|
||||
|
||||
/* KVM trampoline code needs to be close to the interrupt handlers */
|
||||
|
||||
#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
|
||||
#include "../kvm/book3s_64_rmhandlers.S"
|
||||
#endif
|
||||
|
||||
_GLOBAL(generic_secondary_thread_init)
|
||||
mr r24,r3
|
||||
|
||||
|
|
|
@ -206,6 +206,8 @@ MachineCheck:
|
|||
EXCEPTION_PROLOG
|
||||
mfspr r4,SPRN_DAR
|
||||
stw r4,_DAR(r11)
|
||||
li r5,0x00f0
|
||||
mtspr SPRN_DAR,r5 /* Tag DAR, to be used in DTLB Error */
|
||||
mfspr r5,SPRN_DSISR
|
||||
stw r5,_DSISR(r11)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
|
@ -222,6 +224,8 @@ DataAccess:
|
|||
stw r10,_DSISR(r11)
|
||||
mr r5,r10
|
||||
mfspr r4,SPRN_DAR
|
||||
li r10,0x00f0
|
||||
mtspr SPRN_DAR,r10 /* Tag DAR, to be used in DTLB Error */
|
||||
EXC_XFER_EE_LITE(0x300, handle_page_fault)
|
||||
|
||||
/* Instruction access exception.
|
||||
|
@ -244,6 +248,8 @@ Alignment:
|
|||
EXCEPTION_PROLOG
|
||||
mfspr r4,SPRN_DAR
|
||||
stw r4,_DAR(r11)
|
||||
li r5,0x00f0
|
||||
mtspr SPRN_DAR,r5 /* Tag DAR, to be used in DTLB Error */
|
||||
mfspr r5,SPRN_DSISR
|
||||
stw r5,_DSISR(r11)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
|
@ -333,26 +339,20 @@ InstructionTLBMiss:
|
|||
mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
|
||||
lwz r10, 0(r11) /* Get the pte */
|
||||
|
||||
#ifdef CONFIG_SWAP
|
||||
/* do not set the _PAGE_ACCESSED bit of a non-present page */
|
||||
andi. r11, r10, _PAGE_PRESENT
|
||||
beq 4f
|
||||
ori r10, r10, _PAGE_ACCESSED
|
||||
mfspr r11, SPRN_MD_TWC /* get the pte address again */
|
||||
stw r10, 0(r11)
|
||||
4:
|
||||
#else
|
||||
ori r10, r10, _PAGE_ACCESSED
|
||||
stw r10, 0(r11)
|
||||
#endif
|
||||
andi. r11, r10, _PAGE_ACCESSED | _PAGE_PRESENT
|
||||
cmpwi cr0, r11, _PAGE_ACCESSED | _PAGE_PRESENT
|
||||
bne- cr0, 2f
|
||||
|
||||
/* Clear PP lsb, 0x400 */
|
||||
rlwinm r10, r10, 0, 22, 20
|
||||
|
||||
/* The Linux PTE won't go exactly into the MMU TLB.
|
||||
* Software indicator bits 21, 22 and 28 must be clear.
|
||||
* Software indicator bits 22 and 28 must be clear.
|
||||
* Software indicator bits 24, 25, 26, and 27 must be
|
||||
* set. All other Linux PTE bits control the behavior
|
||||
* of the MMU.
|
||||
*/
|
||||
2: li r11, 0x00f0
|
||||
li r11, 0x00f0
|
||||
rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
|
||||
DO_8xx_CPU6(0x2d80, r3)
|
||||
mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
|
||||
|
@ -365,6 +365,22 @@ InstructionTLBMiss:
|
|||
lwz r3, 8(r0)
|
||||
#endif
|
||||
rfi
|
||||
2:
|
||||
mfspr r11, SPRN_SRR1
|
||||
/* clear all error bits as TLB Miss
|
||||
* sets a few unconditionally
|
||||
*/
|
||||
rlwinm r11, r11, 0, 0xffff
|
||||
mtspr SPRN_SRR1, r11
|
||||
|
||||
mfspr r10, SPRN_M_TW /* Restore registers */
|
||||
lwz r11, 0(r0)
|
||||
mtcr r11
|
||||
lwz r11, 4(r0)
|
||||
#ifdef CONFIG_8xx_CPU6
|
||||
lwz r3, 8(r0)
|
||||
#endif
|
||||
b InstructionAccess
|
||||
|
||||
. = 0x1200
|
||||
DataStoreTLBMiss:
|
||||
|
@ -406,29 +422,45 @@ DataStoreTLBMiss:
|
|||
* above.
|
||||
*/
|
||||
rlwimi r11, r10, 0, 27, 27
|
||||
/* Insert the WriteThru flag into the TWC from the Linux PTE.
|
||||
* It is bit 25 in the Linux PTE and bit 30 in the TWC
|
||||
*/
|
||||
rlwimi r11, r10, 32-5, 30, 30
|
||||
DO_8xx_CPU6(0x3b80, r3)
|
||||
mtspr SPRN_MD_TWC, r11
|
||||
|
||||
#ifdef CONFIG_SWAP
|
||||
/* do not set the _PAGE_ACCESSED bit of a non-present page */
|
||||
andi. r11, r10, _PAGE_PRESENT
|
||||
beq 4f
|
||||
ori r10, r10, _PAGE_ACCESSED
|
||||
4:
|
||||
/* and update pte in table */
|
||||
#else
|
||||
ori r10, r10, _PAGE_ACCESSED
|
||||
#endif
|
||||
mfspr r11, SPRN_MD_TWC /* get the pte address again */
|
||||
stw r10, 0(r11)
|
||||
/* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set.
|
||||
* We also need to know if the insn is a load/store, so:
|
||||
* Clear _PAGE_PRESENT and load that which will
|
||||
* trap into DTLB Error with store bit set accordinly.
|
||||
*/
|
||||
/* PRESENT=0x1, ACCESSED=0x20
|
||||
* r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5));
|
||||
* r10 = (r10 & ~PRESENT) | r11;
|
||||
*/
|
||||
rlwinm r11, r10, 32-5, _PAGE_PRESENT
|
||||
and r11, r11, r10
|
||||
rlwimi r10, r11, 0, _PAGE_PRESENT
|
||||
|
||||
/* Honour kernel RO, User NA */
|
||||
/* 0x200 == Extended encoding, bit 22 */
|
||||
/* r11 = (r10 & _PAGE_USER) >> 2 */
|
||||
rlwinm r11, r10, 32-2, 0x200
|
||||
or r10, r11, r10
|
||||
/* r11 = (r10 & _PAGE_RW) >> 1 */
|
||||
rlwinm r11, r10, 32-1, 0x200
|
||||
or r10, r11, r10
|
||||
/* invert RW and 0x200 bits */
|
||||
xori r10, r10, _PAGE_RW | 0x200
|
||||
|
||||
/* The Linux PTE won't go exactly into the MMU TLB.
|
||||
* Software indicator bits 21, 22 and 28 must be clear.
|
||||
* Software indicator bits 22 and 28 must be clear.
|
||||
* Software indicator bits 24, 25, 26, and 27 must be
|
||||
* set. All other Linux PTE bits control the behavior
|
||||
* of the MMU.
|
||||
*/
|
||||
2: li r11, 0x00f0
|
||||
mtspr SPRN_DAR,r11 /* Tag DAR */
|
||||
rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
|
||||
DO_8xx_CPU6(0x3d80, r3)
|
||||
mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
|
||||
|
@ -469,97 +501,10 @@ DataTLBError:
|
|||
stw r10, 0(r0)
|
||||
stw r11, 4(r0)
|
||||
|
||||
/* First, make sure this was a store operation.
|
||||
*/
|
||||
mfspr r10, SPRN_DSISR
|
||||
andis. r11, r10, 0x0200 /* If set, indicates store op */
|
||||
beq 2f
|
||||
|
||||
/* The EA of a data TLB miss is automatically stored in the MD_EPN
|
||||
* register. The EA of a data TLB error is automatically stored in
|
||||
* the DAR, but not the MD_EPN register. We must copy the 20 most
|
||||
* significant bits of the EA from the DAR to MD_EPN before we
|
||||
* start walking the page tables. We also need to copy the CASID
|
||||
* value from the M_CASID register.
|
||||
* Addendum: The EA of a data TLB error is _supposed_ to be stored
|
||||
* in DAR, but it seems that this doesn't happen in some cases, such
|
||||
* as when the error is due to a dcbi instruction to a page with a
|
||||
* TLB that doesn't have the changed bit set. In such cases, there
|
||||
* does not appear to be any way to recover the EA of the error
|
||||
* since it is neither in DAR nor MD_EPN. As a workaround, the
|
||||
* _PAGE_HWWRITE bit is set for all kernel data pages when the PTEs
|
||||
* are initialized in mapin_ram(). This will avoid the problem,
|
||||
* assuming we only use the dcbi instruction on kernel addresses.
|
||||
*/
|
||||
mfspr r10, SPRN_DAR
|
||||
rlwinm r11, r10, 0, 0, 19
|
||||
ori r11, r11, MD_EVALID
|
||||
mfspr r10, SPRN_M_CASID
|
||||
rlwimi r11, r10, 0, 28, 31
|
||||
DO_8xx_CPU6(0x3780, r3)
|
||||
mtspr SPRN_MD_EPN, r11
|
||||
|
||||
mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
|
||||
|
||||
/* If we are faulting a kernel address, we have to use the
|
||||
* kernel page tables.
|
||||
*/
|
||||
andi. r11, r10, 0x0800
|
||||
beq 3f
|
||||
lis r11, swapper_pg_dir@h
|
||||
ori r11, r11, swapper_pg_dir@l
|
||||
rlwimi r10, r11, 0, 2, 19
|
||||
3:
|
||||
lwz r11, 0(r10) /* Get the level 1 entry */
|
||||
rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
|
||||
beq 2f /* If zero, bail */
|
||||
|
||||
/* We have a pte table, so fetch the pte from the table.
|
||||
*/
|
||||
ori r11, r11, 1 /* Set valid bit in physical L2 page */
|
||||
DO_8xx_CPU6(0x3b80, r3)
|
||||
mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
|
||||
mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
|
||||
lwz r10, 0(r11) /* Get the pte */
|
||||
|
||||
andi. r11, r10, _PAGE_RW /* Is it writeable? */
|
||||
beq 2f /* Bail out if not */
|
||||
|
||||
/* Update 'changed', among others.
|
||||
*/
|
||||
#ifdef CONFIG_SWAP
|
||||
ori r10, r10, _PAGE_DIRTY|_PAGE_HWWRITE
|
||||
/* do not set the _PAGE_ACCESSED bit of a non-present page */
|
||||
andi. r11, r10, _PAGE_PRESENT
|
||||
beq 4f
|
||||
ori r10, r10, _PAGE_ACCESSED
|
||||
4:
|
||||
#else
|
||||
ori r10, r10, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
|
||||
#endif
|
||||
mfspr r11, SPRN_MD_TWC /* Get pte address again */
|
||||
stw r10, 0(r11) /* and update pte in table */
|
||||
|
||||
/* The Linux PTE won't go exactly into the MMU TLB.
|
||||
* Software indicator bits 21, 22 and 28 must be clear.
|
||||
* Software indicator bits 24, 25, 26, and 27 must be
|
||||
* set. All other Linux PTE bits control the behavior
|
||||
* of the MMU.
|
||||
*/
|
||||
li r11, 0x00f0
|
||||
rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
|
||||
DO_8xx_CPU6(0x3d80, r3)
|
||||
mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
|
||||
|
||||
mfspr r10, SPRN_M_TW /* Restore registers */
|
||||
lwz r11, 0(r0)
|
||||
mtcr r11
|
||||
lwz r11, 4(r0)
|
||||
#ifdef CONFIG_8xx_CPU6
|
||||
lwz r3, 8(r0)
|
||||
#endif
|
||||
rfi
|
||||
2:
|
||||
cmpwi cr0, r10, 0x00f0
|
||||
beq- FixupDAR /* must be a buggy dcbX, icbi insn. */
|
||||
DARFixed:/* Return from dcbx instruction bug workaround, r10 holds value of DAR */
|
||||
mfspr r10, SPRN_M_TW /* Restore registers */
|
||||
lwz r11, 0(r0)
|
||||
mtcr r11
|
||||
|
@ -588,6 +533,140 @@ DataTLBError:
|
|||
|
||||
. = 0x2000
|
||||
|
||||
/* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions
|
||||
* by decoding the registers used by the dcbx instruction and adding them.
|
||||
* DAR is set to the calculated address and r10 also holds the EA on exit.
|
||||
*/
|
||||
/* define if you don't want to use self modifying code */
|
||||
#define NO_SELF_MODIFYING_CODE
|
||||
FixupDAR:/* Entry point for dcbx workaround. */
|
||||
/* fetch instruction from memory. */
|
||||
mfspr r10, SPRN_SRR0
|
||||
DO_8xx_CPU6(0x3780, r3)
|
||||
mtspr SPRN_MD_EPN, r10
|
||||
mfspr r11, SPRN_M_TWB /* Get level 1 table entry address */
|
||||
cmplwi cr0, r11, 0x0800
|
||||
blt- 3f /* Branch if user space */
|
||||
lis r11, (swapper_pg_dir-PAGE_OFFSET)@h
|
||||
ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l
|
||||
rlwimi r11, r10, 32-20, 0xffc /* r11 = r11&~0xffc|(r10>>20)&0xffc */
|
||||
3: lwz r11, 0(r11) /* Get the level 1 entry */
|
||||
DO_8xx_CPU6(0x3b80, r3)
|
||||
mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
|
||||
mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
|
||||
lwz r11, 0(r11) /* Get the pte */
|
||||
/* concat physical page address(r11) and page offset(r10) */
|
||||
rlwimi r11, r10, 0, 20, 31
|
||||
lwz r11,0(r11)
|
||||
/* Check if it really is a dcbx instruction. */
|
||||
/* dcbt and dcbtst does not generate DTLB Misses/Errors,
|
||||
* no need to include them here */
|
||||
srwi r10, r11, 26 /* check if major OP code is 31 */
|
||||
cmpwi cr0, r10, 31
|
||||
bne- 141f
|
||||
rlwinm r10, r11, 0, 21, 30
|
||||
cmpwi cr0, r10, 2028 /* Is dcbz? */
|
||||
beq+ 142f
|
||||
cmpwi cr0, r10, 940 /* Is dcbi? */
|
||||
beq+ 142f
|
||||
cmpwi cr0, r10, 108 /* Is dcbst? */
|
||||
beq+ 144f /* Fix up store bit! */
|
||||
cmpwi cr0, r10, 172 /* Is dcbf? */
|
||||
beq+ 142f
|
||||
cmpwi cr0, r10, 1964 /* Is icbi? */
|
||||
beq+ 142f
|
||||
141: mfspr r10, SPRN_DAR /* r10 must hold DAR at exit */
|
||||
b DARFixed /* Nope, go back to normal TLB processing */
|
||||
|
||||
144: mfspr r10, SPRN_DSISR
|
||||
rlwinm r10, r10,0,7,5 /* Clear store bit for buggy dcbst insn */
|
||||
mtspr SPRN_DSISR, r10
|
||||
142: /* continue, it was a dcbx, dcbi instruction. */
|
||||
#ifdef CONFIG_8xx_CPU6
|
||||
lwz r3, 8(r0) /* restore r3 from memory */
|
||||
#endif
|
||||
#ifndef NO_SELF_MODIFYING_CODE
|
||||
andis. r10,r11,0x1f /* test if reg RA is r0 */
|
||||
li r10,modified_instr@l
|
||||
dcbtst r0,r10 /* touch for store */
|
||||
rlwinm r11,r11,0,0,20 /* Zero lower 10 bits */
|
||||
oris r11,r11,640 /* Transform instr. to a "add r10,RA,RB" */
|
||||
ori r11,r11,532
|
||||
stw r11,0(r10) /* store add/and instruction */
|
||||
dcbf 0,r10 /* flush new instr. to memory. */
|
||||
icbi 0,r10 /* invalidate instr. cache line */
|
||||
lwz r11, 4(r0) /* restore r11 from memory */
|
||||
mfspr r10, SPRN_M_TW /* restore r10 from M_TW */
|
||||
isync /* Wait until new instr is loaded from memory */
|
||||
modified_instr:
|
||||
.space 4 /* this is where the add instr. is stored */
|
||||
bne+ 143f
|
||||
subf r10,r0,r10 /* r10=r10-r0, only if reg RA is r0 */
|
||||
143: mtdar r10 /* store faulting EA in DAR */
|
||||
b DARFixed /* Go back to normal TLB handling */
|
||||
#else
|
||||
mfctr r10
|
||||
mtdar r10 /* save ctr reg in DAR */
|
||||
rlwinm r10, r11, 24, 24, 28 /* offset into jump table for reg RB */
|
||||
addi r10, r10, 150f@l /* add start of table */
|
||||
mtctr r10 /* load ctr with jump address */
|
||||
xor r10, r10, r10 /* sum starts at zero */
|
||||
bctr /* jump into table */
|
||||
150:
|
||||
add r10, r10, r0 ;b 151f
|
||||
add r10, r10, r1 ;b 151f
|
||||
add r10, r10, r2 ;b 151f
|
||||
add r10, r10, r3 ;b 151f
|
||||
add r10, r10, r4 ;b 151f
|
||||
add r10, r10, r5 ;b 151f
|
||||
add r10, r10, r6 ;b 151f
|
||||
add r10, r10, r7 ;b 151f
|
||||
add r10, r10, r8 ;b 151f
|
||||
add r10, r10, r9 ;b 151f
|
||||
mtctr r11 ;b 154f /* r10 needs special handling */
|
||||
mtctr r11 ;b 153f /* r11 needs special handling */
|
||||
add r10, r10, r12 ;b 151f
|
||||
add r10, r10, r13 ;b 151f
|
||||
add r10, r10, r14 ;b 151f
|
||||
add r10, r10, r15 ;b 151f
|
||||
add r10, r10, r16 ;b 151f
|
||||
add r10, r10, r17 ;b 151f
|
||||
add r10, r10, r18 ;b 151f
|
||||
add r10, r10, r19 ;b 151f
|
||||
add r10, r10, r20 ;b 151f
|
||||
add r10, r10, r21 ;b 151f
|
||||
add r10, r10, r22 ;b 151f
|
||||
add r10, r10, r23 ;b 151f
|
||||
add r10, r10, r24 ;b 151f
|
||||
add r10, r10, r25 ;b 151f
|
||||
add r10, r10, r26 ;b 151f
|
||||
add r10, r10, r27 ;b 151f
|
||||
add r10, r10, r28 ;b 151f
|
||||
add r10, r10, r29 ;b 151f
|
||||
add r10, r10, r30 ;b 151f
|
||||
add r10, r10, r31
|
||||
151:
|
||||
rlwinm. r11,r11,19,24,28 /* offset into jump table for reg RA */
|
||||
beq 152f /* if reg RA is zero, don't add it */
|
||||
addi r11, r11, 150b@l /* add start of table */
|
||||
mtctr r11 /* load ctr with jump address */
|
||||
rlwinm r11,r11,0,16,10 /* make sure we don't execute this more than once */
|
||||
bctr /* jump into table */
|
||||
152:
|
||||
mfdar r11
|
||||
mtctr r11 /* restore ctr reg from DAR */
|
||||
mtdar r10 /* save fault EA to DAR */
|
||||
b DARFixed /* Go back to normal TLB handling */
|
||||
|
||||
/* special handling for r10,r11 since these are modified already */
|
||||
153: lwz r11, 4(r0) /* load r11 from memory */
|
||||
b 155f
|
||||
154: mfspr r11, SPRN_M_TW /* load r10 from M_TW */
|
||||
155: add r10, r10, r11 /* add it */
|
||||
mfctr r11 /* restore r11 */
|
||||
b 151b
|
||||
#endif
|
||||
|
||||
.globl giveup_fpu
|
||||
giveup_fpu:
|
||||
blr
|
||||
|
|
|
@ -943,28 +943,6 @@ _GLOBAL(__setup_e500mc_ivors)
|
|||
sync
|
||||
blr
|
||||
|
||||
/*
|
||||
* extern void loadcam_entry(unsigned int index)
|
||||
*
|
||||
* Load TLBCAM[index] entry in to the L2 CAM MMU
|
||||
*/
|
||||
_GLOBAL(loadcam_entry)
|
||||
lis r4,TLBCAM@ha
|
||||
addi r4,r4,TLBCAM@l
|
||||
mulli r5,r3,TLBCAM_SIZE
|
||||
add r3,r5,r4
|
||||
lwz r4,0(r3)
|
||||
mtspr SPRN_MAS0,r4
|
||||
lwz r4,4(r3)
|
||||
mtspr SPRN_MAS1,r4
|
||||
lwz r4,8(r3)
|
||||
mtspr SPRN_MAS2,r4
|
||||
lwz r4,12(r3)
|
||||
mtspr SPRN_MAS3,r4
|
||||
tlbwe
|
||||
isync
|
||||
blr
|
||||
|
||||
/*
|
||||
* extern void giveup_altivec(struct task_struct *prev)
|
||||
*
|
||||
|
|
|
@ -161,7 +161,7 @@ void _memcpy_fromio(void *dest, const volatile void __iomem *src,
|
|||
dest++;
|
||||
n--;
|
||||
}
|
||||
while(n > 4) {
|
||||
while(n >= 4) {
|
||||
*((u32 *)dest) = *((volatile u32 *)vsrc);
|
||||
eieio();
|
||||
vsrc += 4;
|
||||
|
@ -190,7 +190,7 @@ void _memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n)
|
|||
vdest++;
|
||||
n--;
|
||||
}
|
||||
while(n > 4) {
|
||||
while(n >= 4) {
|
||||
*((volatile u32 *)vdest) = *((volatile u32 *)src);
|
||||
src += 4;
|
||||
vdest += 4;
|
||||
|
|
|
@ -87,7 +87,10 @@ extern int tau_interrupts(int);
|
|||
#endif /* CONFIG_PPC32 */
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
|
||||
#ifndef CONFIG_SPARSE_IRQ
|
||||
EXPORT_SYMBOL(irq_desc);
|
||||
#endif
|
||||
|
||||
int distribute_irqs = 1;
|
||||
|
||||
|
@ -189,33 +192,7 @@ int show_interrupts(struct seq_file *p, void *v)
|
|||
for_each_online_cpu(j)
|
||||
seq_printf(p, "CPU%d ", j);
|
||||
seq_putc(p, '\n');
|
||||
}
|
||||
|
||||
if (i < NR_IRQS) {
|
||||
desc = get_irq_desc(i);
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
action = desc->action;
|
||||
if (!action || !action->handler)
|
||||
goto skip;
|
||||
seq_printf(p, "%3d: ", i);
|
||||
#ifdef CONFIG_SMP
|
||||
for_each_online_cpu(j)
|
||||
seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
|
||||
#else
|
||||
seq_printf(p, "%10u ", kstat_irqs(i));
|
||||
#endif /* CONFIG_SMP */
|
||||
if (desc->chip)
|
||||
seq_printf(p, " %s ", desc->chip->typename);
|
||||
else
|
||||
seq_puts(p, " None ");
|
||||
seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge ");
|
||||
seq_printf(p, " %s", action->name);
|
||||
for (action = action->next; action; action = action->next)
|
||||
seq_printf(p, ", %s", action->name);
|
||||
seq_putc(p, '\n');
|
||||
skip:
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
} else if (i == NR_IRQS) {
|
||||
} else if (i == nr_irqs) {
|
||||
#if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT)
|
||||
if (tau_initialized){
|
||||
seq_puts(p, "TAU: ");
|
||||
|
@ -225,30 +202,68 @@ skip:
|
|||
}
|
||||
#endif /* CONFIG_PPC32 && CONFIG_TAU_INT*/
|
||||
seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
desc = irq_to_desc(i);
|
||||
if (!desc)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
|
||||
action = desc->action;
|
||||
if (!action || !action->handler)
|
||||
goto skip;
|
||||
|
||||
seq_printf(p, "%3d: ", i);
|
||||
#ifdef CONFIG_SMP
|
||||
for_each_online_cpu(j)
|
||||
seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
|
||||
#else
|
||||
seq_printf(p, "%10u ", kstat_irqs(i));
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
if (desc->chip)
|
||||
seq_printf(p, " %s ", desc->chip->name);
|
||||
else
|
||||
seq_puts(p, " None ");
|
||||
|
||||
seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge ");
|
||||
seq_printf(p, " %s", action->name);
|
||||
|
||||
for (action = action->next; action; action = action->next)
|
||||
seq_printf(p, ", %s", action->name);
|
||||
seq_putc(p, '\n');
|
||||
|
||||
skip:
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
void fixup_irqs(cpumask_t map)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
unsigned int irq;
|
||||
static int warned;
|
||||
|
||||
for_each_irq(irq) {
|
||||
cpumask_t mask;
|
||||
|
||||
if (irq_desc[irq].status & IRQ_PER_CPU)
|
||||
desc = irq_to_desc(irq);
|
||||
if (desc && desc->status & IRQ_PER_CPU)
|
||||
continue;
|
||||
|
||||
cpumask_and(&mask, irq_desc[irq].affinity, &map);
|
||||
cpumask_and(&mask, desc->affinity, &map);
|
||||
if (any_online_cpu(mask) == NR_CPUS) {
|
||||
printk("Breaking affinity for irq %i\n", irq);
|
||||
mask = map;
|
||||
}
|
||||
if (irq_desc[irq].chip->set_affinity)
|
||||
irq_desc[irq].chip->set_affinity(irq, &mask);
|
||||
else if (irq_desc[irq].action && !(warned++))
|
||||
if (desc->chip->set_affinity)
|
||||
desc->chip->set_affinity(irq, &mask);
|
||||
else if (desc->action && !(warned++))
|
||||
printk("Cannot set affinity for irq %i\n", irq);
|
||||
}
|
||||
|
||||
|
@ -275,7 +290,7 @@ static inline void handle_one_irq(unsigned int irq)
|
|||
return;
|
||||
}
|
||||
|
||||
desc = irq_desc + irq;
|
||||
desc = irq_to_desc(irq);
|
||||
saved_sp_limit = current->thread.ksp_limit;
|
||||
|
||||
irqtp->task = curtp->task;
|
||||
|
@ -541,7 +556,7 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
|
|||
smp_wmb();
|
||||
|
||||
/* Clear norequest flags */
|
||||
get_irq_desc(i)->status &= ~IRQ_NOREQUEST;
|
||||
irq_to_desc(i)->status &= ~IRQ_NOREQUEST;
|
||||
|
||||
/* Legacy flags are left to default at this point,
|
||||
* one can then use irq_create_mapping() to
|
||||
|
@ -607,8 +622,16 @@ void irq_set_virq_count(unsigned int count)
|
|||
static int irq_setup_virq(struct irq_host *host, unsigned int virq,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
|
||||
desc = irq_to_desc_alloc_node(virq, 0);
|
||||
if (!desc) {
|
||||
pr_debug("irq: -> allocating desc failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Clear IRQ_NOREQUEST flag */
|
||||
get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
|
||||
desc->status &= ~IRQ_NOREQUEST;
|
||||
|
||||
/* map it */
|
||||
smp_wmb();
|
||||
|
@ -617,11 +640,14 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,
|
|||
|
||||
if (host->ops->map(host, virq, hwirq)) {
|
||||
pr_debug("irq: -> mapping failed, freeing\n");
|
||||
irq_free_virt(virq, 1);
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
irq_free_virt(virq, 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int irq_create_direct_mapping(struct irq_host *host)
|
||||
|
@ -705,7 +731,7 @@ unsigned int irq_create_mapping(struct irq_host *host,
|
|||
EXPORT_SYMBOL_GPL(irq_create_mapping);
|
||||
|
||||
unsigned int irq_create_of_mapping(struct device_node *controller,
|
||||
u32 *intspec, unsigned int intsize)
|
||||
const u32 *intspec, unsigned int intsize)
|
||||
{
|
||||
struct irq_host *host;
|
||||
irq_hw_number_t hwirq;
|
||||
|
@ -738,7 +764,7 @@ unsigned int irq_create_of_mapping(struct device_node *controller,
|
|||
|
||||
/* Set type if specified and different than the current one */
|
||||
if (type != IRQ_TYPE_NONE &&
|
||||
type != (get_irq_desc(virq)->status & IRQF_TRIGGER_MASK))
|
||||
type != (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK))
|
||||
set_irq_type(virq, type);
|
||||
return virq;
|
||||
}
|
||||
|
@ -810,7 +836,7 @@ void irq_dispose_mapping(unsigned int virq)
|
|||
irq_map[virq].hwirq = host->inval_irq;
|
||||
|
||||
/* Set some flags */
|
||||
get_irq_desc(virq)->status |= IRQ_NOREQUEST;
|
||||
irq_to_desc(virq)->status |= IRQ_NOREQUEST;
|
||||
|
||||
/* Free it */
|
||||
irq_free_virt(virq, 1);
|
||||
|
@ -1002,12 +1028,24 @@ void irq_free_virt(unsigned int virq, unsigned int count)
|
|||
spin_unlock_irqrestore(&irq_big_lock, flags);
|
||||
}
|
||||
|
||||
void irq_early_init(void)
|
||||
int arch_early_irq_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
struct irq_desc *desc;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NR_IRQS; i++)
|
||||
get_irq_desc(i)->status |= IRQ_NOREQUEST;
|
||||
for (i = 0; i < NR_IRQS; i++) {
|
||||
desc = irq_to_desc(i);
|
||||
if (desc)
|
||||
desc->status |= IRQ_NOREQUEST;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_init_chip_data(struct irq_desc *desc, int node)
|
||||
{
|
||||
desc->status |= IRQ_NOREQUEST;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We need to create the radix trees late */
|
||||
|
@ -1069,16 +1107,19 @@ static int virq_debug_show(struct seq_file *m, void *private)
|
|||
seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq",
|
||||
"chip name", "host name");
|
||||
|
||||
for (i = 1; i < NR_IRQS; i++) {
|
||||
desc = get_irq_desc(i);
|
||||
for (i = 1; i < nr_irqs; i++) {
|
||||
desc = irq_to_desc(i);
|
||||
if (!desc)
|
||||
continue;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
|
||||
if (desc->action && desc->action->handler) {
|
||||
seq_printf(m, "%5d ", i);
|
||||
seq_printf(m, "0x%05lx ", virq_to_hw(i));
|
||||
|
||||
if (desc->chip && desc->chip->typename)
|
||||
p = desc->chip->typename;
|
||||
if (desc->chip && desc->chip->name)
|
||||
p = desc->chip->name;
|
||||
else
|
||||
p = none;
|
||||
seq_printf(m, "%-15s ", p);
|
||||
|
|
|
@ -781,9 +781,9 @@ static int __init lparcfg_init(void)
|
|||
!firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
mode |= S_IWUSR;
|
||||
|
||||
ent = proc_create("ppc64/lparcfg", mode, NULL, &lparcfg_fops);
|
||||
ent = proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_fops);
|
||||
if (!ent) {
|
||||
printk(KERN_ERR "Failed to create ppc64/lparcfg\n");
|
||||
printk(KERN_ERR "Failed to create powerpc/lparcfg\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
|
|
@ -502,15 +502,7 @@ _GLOBAL(clear_pages)
|
|||
li r0,PAGE_SIZE/L1_CACHE_BYTES
|
||||
slw r0,r0,r4
|
||||
mtctr r0
|
||||
#ifdef CONFIG_8xx
|
||||
li r4, 0
|
||||
1: stw r4, 0(r3)
|
||||
stw r4, 4(r3)
|
||||
stw r4, 8(r3)
|
||||
stw r4, 12(r3)
|
||||
#else
|
||||
1: dcbz 0,r3
|
||||
#endif
|
||||
addi r3,r3,L1_CACHE_BYTES
|
||||
bdnz 1b
|
||||
blr
|
||||
|
@ -535,15 +527,6 @@ _GLOBAL(copy_page)
|
|||
addi r3,r3,-4
|
||||
addi r4,r4,-4
|
||||
|
||||
#ifdef CONFIG_8xx
|
||||
/* don't use prefetch on 8xx */
|
||||
li r0,4096/L1_CACHE_BYTES
|
||||
mtctr r0
|
||||
1: COPY_16_BYTES
|
||||
bdnz 1b
|
||||
blr
|
||||
|
||||
#else /* not 8xx, we can prefetch */
|
||||
li r5,4
|
||||
|
||||
#if MAX_COPY_PREFETCH > 1
|
||||
|
@ -584,7 +567,6 @@ _GLOBAL(copy_page)
|
|||
li r0,MAX_COPY_PREFETCH
|
||||
li r11,4
|
||||
b 2b
|
||||
#endif /* CONFIG_8xx */
|
||||
|
||||
/*
|
||||
* void atomic_clear_mask(atomic_t mask, atomic_t *addr)
|
||||
|
|
|
@ -139,8 +139,8 @@ out:
|
|||
|
||||
}
|
||||
|
||||
static int dev_nvram_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
static long dev_nvram_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
switch(cmd) {
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
|
@ -169,11 +169,11 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file,
|
|||
}
|
||||
|
||||
const struct file_operations nvram_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = dev_nvram_llseek,
|
||||
.read = dev_nvram_read,
|
||||
.write = dev_nvram_write,
|
||||
.ioctl = dev_nvram_ioctl,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = dev_nvram_llseek,
|
||||
.read = dev_nvram_read,
|
||||
.write = dev_nvram_write,
|
||||
.unlocked_ioctl = dev_nvram_ioctl,
|
||||
};
|
||||
|
||||
static struct miscdevice nvram_dev = {
|
||||
|
@ -184,7 +184,7 @@ static struct miscdevice nvram_dev = {
|
|||
|
||||
|
||||
#ifdef DEBUG_NVRAM
|
||||
static void nvram_print_partitions(char * label)
|
||||
static void __init nvram_print_partitions(char * label)
|
||||
{
|
||||
struct list_head * p;
|
||||
struct nvram_partition * tmp_part;
|
||||
|
@ -202,7 +202,7 @@ static void nvram_print_partitions(char * label)
|
|||
#endif
|
||||
|
||||
|
||||
static int nvram_write_header(struct nvram_partition * part)
|
||||
static int __init nvram_write_header(struct nvram_partition * part)
|
||||
{
|
||||
loff_t tmp_index;
|
||||
int rc;
|
||||
|
@ -214,7 +214,7 @@ static int nvram_write_header(struct nvram_partition * part)
|
|||
}
|
||||
|
||||
|
||||
static unsigned char nvram_checksum(struct nvram_header *p)
|
||||
static unsigned char __init nvram_checksum(struct nvram_header *p)
|
||||
{
|
||||
unsigned int c_sum, c_sum2;
|
||||
unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */
|
||||
|
@ -228,32 +228,7 @@ static unsigned char nvram_checksum(struct nvram_header *p)
|
|||
return c_sum;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find an nvram partition, sig can be 0 for any
|
||||
* partition or name can be NULL for any name, else
|
||||
* tries to match both
|
||||
*/
|
||||
struct nvram_partition *nvram_find_partition(int sig, const char *name)
|
||||
{
|
||||
struct nvram_partition * part;
|
||||
struct list_head * p;
|
||||
|
||||
list_for_each(p, &nvram_part->partition) {
|
||||
part = list_entry(p, struct nvram_partition, partition);
|
||||
|
||||
if (sig && part->header.signature != sig)
|
||||
continue;
|
||||
if (name && 0 != strncmp(name, part->header.name, 12))
|
||||
continue;
|
||||
return part;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(nvram_find_partition);
|
||||
|
||||
|
||||
static int nvram_remove_os_partition(void)
|
||||
static int __init nvram_remove_os_partition(void)
|
||||
{
|
||||
struct list_head *i;
|
||||
struct list_head *j;
|
||||
|
@ -319,7 +294,7 @@ static int nvram_remove_os_partition(void)
|
|||
* Will create a partition starting at the first free
|
||||
* space found if space has enough room.
|
||||
*/
|
||||
static int nvram_create_os_partition(void)
|
||||
static int __init nvram_create_os_partition(void)
|
||||
{
|
||||
struct nvram_partition *part;
|
||||
struct nvram_partition *new_part;
|
||||
|
@ -422,7 +397,7 @@ static int nvram_create_os_partition(void)
|
|||
* 5.) If the max chunk cannot be allocated then try finding a chunk
|
||||
* that will satisfy the minum needed (NVRAM_MIN_REQ).
|
||||
*/
|
||||
static int nvram_setup_partition(void)
|
||||
static int __init nvram_setup_partition(void)
|
||||
{
|
||||
struct list_head * p;
|
||||
struct nvram_partition * part;
|
||||
|
@ -480,7 +455,7 @@ static int nvram_setup_partition(void)
|
|||
}
|
||||
|
||||
|
||||
static int nvram_scan_partitions(void)
|
||||
static int __init nvram_scan_partitions(void)
|
||||
{
|
||||
loff_t cur_index = 0;
|
||||
struct nvram_header phead;
|
||||
|
@ -706,6 +681,9 @@ int nvram_clear_error_log(void)
|
|||
int clear_word = ERR_FLAG_ALREADY_LOGGED;
|
||||
int rc;
|
||||
|
||||
if (nvram_error_log_index == -1)
|
||||
return -1;
|
||||
|
||||
tmp_index = nvram_error_log_index;
|
||||
|
||||
rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);
|
||||
|
|
|
@ -119,13 +119,6 @@ static void perf_callchain_kernel(struct pt_regs *regs,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
#define is_huge_psize(pagesize) (HPAGE_SHIFT && mmu_huge_psizes[pagesize])
|
||||
#else
|
||||
#define is_huge_psize(pagesize) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On 64-bit we don't want to invoke hash_page on user addresses from
|
||||
* interrupt context, so if the access faults, we read the page tables
|
||||
|
@ -135,7 +128,7 @@ static int read_user_stack_slow(void __user *ptr, void *ret, int nb)
|
|||
{
|
||||
pgd_t *pgdir;
|
||||
pte_t *ptep, pte;
|
||||
int pagesize;
|
||||
unsigned shift;
|
||||
unsigned long addr = (unsigned long) ptr;
|
||||
unsigned long offset;
|
||||
unsigned long pfn;
|
||||
|
@ -145,17 +138,14 @@ static int read_user_stack_slow(void __user *ptr, void *ret, int nb)
|
|||
if (!pgdir)
|
||||
return -EFAULT;
|
||||
|
||||
pagesize = get_slice_psize(current->mm, addr);
|
||||
ptep = find_linux_pte_or_hugepte(pgdir, addr, &shift);
|
||||
if (!shift)
|
||||
shift = PAGE_SHIFT;
|
||||
|
||||
/* align address to page boundary */
|
||||
offset = addr & ((1ul << mmu_psize_defs[pagesize].shift) - 1);
|
||||
offset = addr & ((1UL << shift) - 1);
|
||||
addr -= offset;
|
||||
|
||||
if (is_huge_psize(pagesize))
|
||||
ptep = huge_pte_offset(current->mm, addr);
|
||||
else
|
||||
ptep = find_linux_pte(pgdir, addr);
|
||||
|
||||
if (ptep == NULL)
|
||||
return -EFAULT;
|
||||
pte = *ptep;
|
||||
|
|
|
@ -96,8 +96,6 @@ EXPORT_SYMBOL(copy_4K_page);
|
|||
EXPORT_SYMBOL(isa_io_base);
|
||||
EXPORT_SYMBOL(isa_mem_base);
|
||||
EXPORT_SYMBOL(pci_dram_offset);
|
||||
EXPORT_SYMBOL(pci_alloc_consistent);
|
||||
EXPORT_SYMBOL(pci_free_consistent);
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
EXPORT_SYMBOL(start_thread);
|
||||
|
@ -162,7 +160,6 @@ EXPORT_SYMBOL(screen_info);
|
|||
|
||||
#ifdef CONFIG_PPC32
|
||||
EXPORT_SYMBOL(timer_interrupt);
|
||||
EXPORT_SYMBOL(irq_desc);
|
||||
EXPORT_SYMBOL(tb_ticks_per_jiffy);
|
||||
EXPORT_SYMBOL(cacheable_memcpy);
|
||||
EXPORT_SYMBOL(cacheable_memzero);
|
||||
|
|
|
@ -28,55 +28,7 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
static loff_t page_map_seek( struct file *file, loff_t off, int whence);
|
||||
static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes,
|
||||
loff_t *ppos);
|
||||
static int page_map_mmap( struct file *file, struct vm_area_struct *vma );
|
||||
|
||||
static const struct file_operations page_map_fops = {
|
||||
.llseek = page_map_seek,
|
||||
.read = page_map_read,
|
||||
.mmap = page_map_mmap
|
||||
};
|
||||
|
||||
/*
|
||||
* Create the ppc64 and ppc64/rtas directories early. This allows us to
|
||||
* assume that they have been previously created in drivers.
|
||||
*/
|
||||
static int __init proc_ppc64_create(void)
|
||||
{
|
||||
struct proc_dir_entry *root;
|
||||
|
||||
root = proc_mkdir("ppc64", NULL);
|
||||
if (!root)
|
||||
return 1;
|
||||
|
||||
if (!of_find_node_by_path("/rtas"))
|
||||
return 0;
|
||||
|
||||
if (!proc_mkdir("rtas", root))
|
||||
return 1;
|
||||
|
||||
if (!proc_symlink("rtas", NULL, "ppc64/rtas"))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
core_initcall(proc_ppc64_create);
|
||||
|
||||
static int __init proc_ppc64_init(void)
|
||||
{
|
||||
struct proc_dir_entry *pde;
|
||||
|
||||
pde = proc_create_data("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL,
|
||||
&page_map_fops, vdso_data);
|
||||
if (!pde)
|
||||
return 1;
|
||||
pde->size = PAGE_SIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
__initcall(proc_ppc64_init);
|
||||
#ifdef CONFIG_PPC64
|
||||
|
||||
static loff_t page_map_seek( struct file *file, loff_t off, int whence)
|
||||
{
|
||||
|
@ -120,3 +72,55 @@ static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations page_map_fops = {
|
||||
.llseek = page_map_seek,
|
||||
.read = page_map_read,
|
||||
.mmap = page_map_mmap
|
||||
};
|
||||
|
||||
|
||||
static int __init proc_ppc64_init(void)
|
||||
{
|
||||
struct proc_dir_entry *pde;
|
||||
|
||||
pde = proc_create_data("powerpc/systemcfg", S_IFREG|S_IRUGO, NULL,
|
||||
&page_map_fops, vdso_data);
|
||||
if (!pde)
|
||||
return 1;
|
||||
pde->size = PAGE_SIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
__initcall(proc_ppc64_init);
|
||||
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
/*
|
||||
* Create the ppc64 and ppc64/rtas directories early. This allows us to
|
||||
* assume that they have been previously created in drivers.
|
||||
*/
|
||||
static int __init proc_ppc64_create(void)
|
||||
{
|
||||
struct proc_dir_entry *root;
|
||||
|
||||
root = proc_mkdir("powerpc", NULL);
|
||||
if (!root)
|
||||
return 1;
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
if (!proc_symlink("ppc64", NULL, "powerpc"))
|
||||
pr_err("Failed to create link /proc/ppc64 -> /proc/powerpc\n");
|
||||
#endif
|
||||
|
||||
if (!of_find_node_by_path("/rtas"))
|
||||
return 0;
|
||||
|
||||
if (!proc_mkdir("rtas", root))
|
||||
return 1;
|
||||
|
||||
if (!proc_symlink("rtas", NULL, "powerpc/rtas"))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
core_initcall(proc_ppc64_create);
|
|
@ -6,7 +6,7 @@
|
|||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* /proc/ppc64/rtas/firmware_flash interface
|
||||
* /proc/powerpc/rtas/firmware_flash interface
|
||||
*
|
||||
* This file implements a firmware_flash interface to pump a firmware
|
||||
* image into the kernel. At reboot time rtas_restart() will see the
|
||||
|
@ -740,7 +740,7 @@ static int __init rtas_flash_init(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
firmware_flash_pde = create_flash_pde("ppc64/rtas/"
|
||||
firmware_flash_pde = create_flash_pde("powerpc/rtas/"
|
||||
FIRMWARE_FLASH_NAME,
|
||||
&rtas_flash_operations);
|
||||
if (firmware_flash_pde == NULL) {
|
||||
|
@ -754,7 +754,7 @@ static int __init rtas_flash_init(void)
|
|||
if (rc != 0)
|
||||
goto cleanup;
|
||||
|
||||
firmware_update_pde = create_flash_pde("ppc64/rtas/"
|
||||
firmware_update_pde = create_flash_pde("powerpc/rtas/"
|
||||
FIRMWARE_UPDATE_NAME,
|
||||
&rtas_flash_operations);
|
||||
if (firmware_update_pde == NULL) {
|
||||
|
@ -768,7 +768,7 @@ static int __init rtas_flash_init(void)
|
|||
if (rc != 0)
|
||||
goto cleanup;
|
||||
|
||||
validate_pde = create_flash_pde("ppc64/rtas/" VALIDATE_FLASH_NAME,
|
||||
validate_pde = create_flash_pde("powerpc/rtas/" VALIDATE_FLASH_NAME,
|
||||
&validate_flash_operations);
|
||||
if (validate_pde == NULL) {
|
||||
rc = -ENOMEM;
|
||||
|
@ -781,7 +781,7 @@ static int __init rtas_flash_init(void)
|
|||
if (rc != 0)
|
||||
goto cleanup;
|
||||
|
||||
manage_pde = create_flash_pde("ppc64/rtas/" MANAGE_FLASH_NAME,
|
||||
manage_pde = create_flash_pde("powerpc/rtas/" MANAGE_FLASH_NAME,
|
||||
&manage_flash_operations);
|
||||
if (manage_pde == NULL) {
|
||||
rc = -ENOMEM;
|
||||
|
|
|
@ -39,6 +39,7 @@ static unsigned long rtas_log_start;
|
|||
static unsigned long rtas_log_size;
|
||||
|
||||
static int surveillance_timeout = -1;
|
||||
|
||||
static unsigned int rtas_error_log_max;
|
||||
static unsigned int rtas_error_log_buffer_max;
|
||||
|
||||
|
@ -213,9 +214,11 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
/* Write error to NVRAM */
|
||||
if (logging_enabled && !(err_type & ERR_FLAG_BOOT))
|
||||
nvram_write_error_log(buf, len, err_type, error_log_cnt);
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
/*
|
||||
* rtas errors can occur during boot, and we do want to capture
|
||||
|
@ -264,7 +267,6 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
|
|||
|
||||
}
|
||||
|
||||
|
||||
static int rtas_log_open(struct inode * inode, struct file * file)
|
||||
{
|
||||
return 0;
|
||||
|
@ -300,6 +302,7 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf,
|
|||
return -ENOMEM;
|
||||
|
||||
spin_lock_irqsave(&rtasd_log_lock, s);
|
||||
|
||||
/* if it's 0, then we know we got the last one (the one in NVRAM) */
|
||||
while (rtas_log_size == 0) {
|
||||
if (file->f_flags & O_NONBLOCK) {
|
||||
|
@ -313,7 +316,9 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf,
|
|||
error = -ENODATA;
|
||||
goto out;
|
||||
}
|
||||
#ifdef CONFIG_PPC64
|
||||
nvram_clear_error_log();
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
spin_unlock_irqrestore(&rtasd_log_lock, s);
|
||||
error = wait_event_interruptible(rtas_log_wait, rtas_log_size);
|
||||
|
@ -427,14 +432,11 @@ static void rtas_event_scan(struct work_struct *w)
|
|||
put_online_cpus();
|
||||
}
|
||||
|
||||
static void start_event_scan(void)
|
||||
#ifdef CONFIG_PPC64
|
||||
static void retreive_nvram_error_log(void)
|
||||
{
|
||||
unsigned int err_type;
|
||||
int rc;
|
||||
|
||||
printk(KERN_DEBUG "RTAS daemon started\n");
|
||||
pr_debug("rtasd: will sleep for %d milliseconds\n",
|
||||
(30000 / rtas_event_scan_rate));
|
||||
unsigned int err_type ;
|
||||
int rc ;
|
||||
|
||||
/* See if we have any error stored in NVRAM */
|
||||
memset(logdata, 0, rtas_error_log_max);
|
||||
|
@ -442,12 +444,26 @@ static void start_event_scan(void)
|
|||
&err_type, &error_log_cnt);
|
||||
/* We can use rtas_log_buf now */
|
||||
logging_enabled = 1;
|
||||
|
||||
if (!rc) {
|
||||
if (err_type != ERR_FLAG_ALREADY_LOGGED) {
|
||||
pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else /* CONFIG_PPC64 */
|
||||
static void retreive_nvram_error_log(void)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
static void start_event_scan(void)
|
||||
{
|
||||
printk(KERN_DEBUG "RTAS daemon started\n");
|
||||
pr_debug("rtasd: will sleep for %d milliseconds\n",
|
||||
(30000 / rtas_event_scan_rate));
|
||||
|
||||
/* Retreive errors from nvram if any */
|
||||
retreive_nvram_error_log();
|
||||
|
||||
schedule_delayed_work_on(first_cpu(cpu_online_map), &event_scan_work,
|
||||
event_scan_delay);
|
||||
|
@ -457,13 +473,13 @@ static int __init rtas_init(void)
|
|||
{
|
||||
struct proc_dir_entry *entry;
|
||||
|
||||
if (!machine_is(pseries))
|
||||
if (!machine_is(pseries) && !machine_is(chrp))
|
||||
return 0;
|
||||
|
||||
/* No RTAS */
|
||||
event_scan = rtas_token("event-scan");
|
||||
if (event_scan == RTAS_UNKNOWN_SERVICE) {
|
||||
printk(KERN_DEBUG "rtasd: no event-scan on system\n");
|
||||
printk(KERN_INFO "rtasd: No event-scan on system\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -483,7 +499,7 @@ static int __init rtas_init(void)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
entry = proc_create("ppc64/rtas/error_log", S_IRUSR, NULL,
|
||||
entry = proc_create("powerpc/rtas/error_log", S_IRUSR, NULL,
|
||||
&proc_rtas_log_operations);
|
||||
if (!entry)
|
||||
printk(KERN_ERR "Failed to create error_log proc entry\n");
|
||||
|
@ -492,11 +508,16 @@ static int __init rtas_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
__initcall(rtas_init);
|
||||
|
||||
static int __init surveillance_setup(char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* We only do surveillance on pseries */
|
||||
if (!machine_is(pseries))
|
||||
return 0;
|
||||
|
||||
if (get_option(&str,&i)) {
|
||||
if (i >= 0 && i <= 255)
|
||||
surveillance_timeout = i;
|
||||
|
@ -504,6 +525,7 @@ static int __init surveillance_setup(char *str)
|
|||
|
||||
return 1;
|
||||
}
|
||||
__setup("surveillance=", surveillance_setup);
|
||||
|
||||
static int __init rtasmsgs_setup(char *str)
|
||||
{
|
||||
|
@ -514,6 +536,4 @@ static int __init rtasmsgs_setup(char *str)
|
|||
|
||||
return 1;
|
||||
}
|
||||
__initcall(rtas_init);
|
||||
__setup("surveillance=", surveillance_setup);
|
||||
__setup("rtasmsgs=", rtasmsgs_setup);
|
|
@ -356,11 +356,6 @@ void __init setup_system(void)
|
|||
*/
|
||||
initialize_cache_info();
|
||||
|
||||
/*
|
||||
* Initialize irq remapping subsystem
|
||||
*/
|
||||
irq_early_init();
|
||||
|
||||
#ifdef CONFIG_PPC_RTAS
|
||||
/*
|
||||
* Initialize RTAS if available
|
||||
|
|
|
@ -218,6 +218,9 @@ void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *))
|
|||
|
||||
static void stop_this_cpu(void *dummy)
|
||||
{
|
||||
/* Remove this CPU */
|
||||
set_cpu_online(smp_processor_id(), false);
|
||||
|
||||
local_irq_disable();
|
||||
while (1)
|
||||
;
|
||||
|
|
|
@ -461,6 +461,25 @@ static void unregister_cpu_online(unsigned int cpu)
|
|||
|
||||
cacheinfo_cpu_offline(cpu);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
|
||||
ssize_t arch_cpu_probe(const char *buf, size_t count)
|
||||
{
|
||||
if (ppc_md.cpu_probe)
|
||||
return ppc_md.cpu_probe(buf, count);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ssize_t arch_cpu_release(const char *buf, size_t count)
|
||||
{
|
||||
if (ppc_md.cpu_release)
|
||||
return ppc_md.cpu_release(buf, count);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
|
||||
|
||||
#endif /* CONFIG_HOTPLUG_CPU */
|
||||
|
||||
static int __cpuinit sysfs_cpu_notify(struct notifier_block *self,
|
||||
|
|
|
@ -269,6 +269,7 @@ void account_system_vtime(struct task_struct *tsk)
|
|||
per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled;
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(account_system_vtime);
|
||||
|
||||
/*
|
||||
* Transfer the user and system times accumulated in the paca
|
||||
|
|
|
@ -198,28 +198,6 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
|
|||
info.si_code = code;
|
||||
info.si_addr = (void __user *) addr;
|
||||
force_sig_info(signr, &info, current);
|
||||
|
||||
/*
|
||||
* Init gets no signals that it doesn't have a handler for.
|
||||
* That's all very well, but if it has caused a synchronous
|
||||
* exception and we ignore the resulting signal, it will just
|
||||
* generate the same exception over and over again and we get
|
||||
* nowhere. Better to kill it and let the kernel panic.
|
||||
*/
|
||||
if (is_global_init(current)) {
|
||||
__sighandler_t handler;
|
||||
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
handler = current->sighand->action[signr-1].sa.sa_handler;
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
if (handler == SIG_DFL) {
|
||||
/* init has generated a synchronous exception
|
||||
and it doesn't have a handler for the signal */
|
||||
printk(KERN_CRIT "init has generated signal %d "
|
||||
"but has no handler for it\n", signr);
|
||||
do_exit(signr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
|
|
|
@ -58,7 +58,7 @@ _GLOBAL(load_up_altivec)
|
|||
* all 1's
|
||||
*/
|
||||
mfspr r4,SPRN_VRSAVE
|
||||
cmpdi 0,r4,0
|
||||
cmpwi 0,r4,0
|
||||
bne+ 1f
|
||||
li r4,-1
|
||||
mtspr SPRN_VRSAVE,r4
|
||||
|
|
|
@ -21,6 +21,23 @@ config KVM
|
|||
select PREEMPT_NOTIFIERS
|
||||
select ANON_INODES
|
||||
|
||||
config KVM_BOOK3S_64_HANDLER
|
||||
bool
|
||||
|
||||
config KVM_BOOK3S_64
|
||||
tristate "KVM support for PowerPC book3s_64 processors"
|
||||
depends on EXPERIMENTAL && PPC64
|
||||
select KVM
|
||||
select KVM_BOOK3S_64_HANDLER
|
||||
---help---
|
||||
Support running unmodified book3s_64 and book3s_32 guest kernels
|
||||
in virtual machines on book3s_64 host processors.
|
||||
|
||||
This module provides access to the hardware capabilities through
|
||||
a character device node named /dev/kvm.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config KVM_440
|
||||
bool "KVM support for PowerPC 440 processors"
|
||||
depends on EXPERIMENTAL && 44x
|
||||
|
|
|
@ -12,26 +12,45 @@ CFLAGS_44x_tlb.o := -I.
|
|||
CFLAGS_e500_tlb.o := -I.
|
||||
CFLAGS_emulate.o := -I.
|
||||
|
||||
kvm-objs := $(common-objs-y) powerpc.o emulate.o
|
||||
common-objs-y += powerpc.o emulate.o
|
||||
obj-$(CONFIG_KVM_EXIT_TIMING) += timing.o
|
||||
obj-$(CONFIG_KVM) += kvm.o
|
||||
obj-$(CONFIG_KVM_BOOK3S_64_HANDLER) += book3s_64_exports.o
|
||||
|
||||
AFLAGS_booke_interrupts.o := -I$(obj)
|
||||
|
||||
kvm-440-objs := \
|
||||
$(common-objs-y) \
|
||||
booke.o \
|
||||
booke_emulate.o \
|
||||
booke_interrupts.o \
|
||||
44x.o \
|
||||
44x_tlb.o \
|
||||
44x_emulate.o
|
||||
obj-$(CONFIG_KVM_440) += kvm-440.o
|
||||
kvm-objs-$(CONFIG_KVM_440) := $(kvm-440-objs)
|
||||
|
||||
kvm-e500-objs := \
|
||||
$(common-objs-y) \
|
||||
booke.o \
|
||||
booke_emulate.o \
|
||||
booke_interrupts.o \
|
||||
e500.o \
|
||||
e500_tlb.o \
|
||||
e500_emulate.o
|
||||
obj-$(CONFIG_KVM_E500) += kvm-e500.o
|
||||
kvm-objs-$(CONFIG_KVM_E500) := $(kvm-e500-objs)
|
||||
|
||||
kvm-book3s_64-objs := \
|
||||
$(common-objs-y) \
|
||||
book3s.o \
|
||||
book3s_64_emulate.o \
|
||||
book3s_64_interrupts.o \
|
||||
book3s_64_mmu_host.o \
|
||||
book3s_64_mmu.o \
|
||||
book3s_32_mmu.o
|
||||
kvm-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-objs)
|
||||
|
||||
kvm-objs := $(kvm-objs-m) $(kvm-objs-y)
|
||||
|
||||
obj-$(CONFIG_KVM_440) += kvm.o
|
||||
obj-$(CONFIG_KVM_E500) += kvm.o
|
||||
obj-$(CONFIG_KVM_BOOK3S_64) += kvm.o
|
||||
|
||||
|
|
974
arch/powerpc/kvm/book3s.c
Normal file
974
arch/powerpc/kvm/book3s.c
Normal file
|
@ -0,0 +1,974 @@
|
|||
/*
|
||||
* Copyright (C) 2009. SUSE Linux Products GmbH. All rights reserved.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Graf <agraf@suse.de>
|
||||
* Kevin Wolf <mail@kevin-wolf.de>
|
||||
*
|
||||
* Description:
|
||||
* This file is derived from arch/powerpc/kvm/44x.c,
|
||||
* by Hollis Blanchard <hollisb@us.ibm.com>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2, as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <asm/reg.h>
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/kvm_ppc.h>
|
||||
#include <asm/kvm_book3s.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
|
||||
|
||||
/* #define EXIT_DEBUG */
|
||||
/* #define EXIT_DEBUG_SIMPLE */
|
||||
|
||||
/* Without AGGRESSIVE_DEC we only fire off a DEC interrupt when DEC turns 0.
|
||||
* When set, we retrigger a DEC interrupt after that if DEC <= 0.
|
||||
* PPC32 Linux runs faster without AGGRESSIVE_DEC, PPC64 Linux requires it. */
|
||||
|
||||
/* #define AGGRESSIVE_DEC */
|
||||
|
||||
struct kvm_stats_debugfs_item debugfs_entries[] = {
|
||||
{ "exits", VCPU_STAT(sum_exits) },
|
||||
{ "mmio", VCPU_STAT(mmio_exits) },
|
||||
{ "sig", VCPU_STAT(signal_exits) },
|
||||
{ "sysc", VCPU_STAT(syscall_exits) },
|
||||
{ "inst_emu", VCPU_STAT(emulated_inst_exits) },
|
||||
{ "dec", VCPU_STAT(dec_exits) },
|
||||
{ "ext_intr", VCPU_STAT(ext_intr_exits) },
|
||||
{ "queue_intr", VCPU_STAT(queue_intr) },
|
||||
{ "halt_wakeup", VCPU_STAT(halt_wakeup) },
|
||||
{ "pf_storage", VCPU_STAT(pf_storage) },
|
||||
{ "sp_storage", VCPU_STAT(sp_storage) },
|
||||
{ "pf_instruc", VCPU_STAT(pf_instruc) },
|
||||
{ "sp_instruc", VCPU_STAT(sp_instruc) },
|
||||
{ "ld", VCPU_STAT(ld) },
|
||||
{ "ld_slow", VCPU_STAT(ld_slow) },
|
||||
{ "st", VCPU_STAT(st) },
|
||||
{ "st_slow", VCPU_STAT(st_slow) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
void kvmppc_core_load_host_debugstate(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
}
|
||||
|
||||
void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
}
|
||||
|
||||
void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
||||
{
|
||||
memcpy(get_paca()->kvm_slb, to_book3s(vcpu)->slb_shadow, sizeof(get_paca()->kvm_slb));
|
||||
get_paca()->kvm_slb_max = to_book3s(vcpu)->slb_shadow_max;
|
||||
}
|
||||
|
||||
void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
memcpy(to_book3s(vcpu)->slb_shadow, get_paca()->kvm_slb, sizeof(get_paca()->kvm_slb));
|
||||
to_book3s(vcpu)->slb_shadow_max = get_paca()->kvm_slb_max;
|
||||
}
|
||||
|
||||
#if defined(AGGRESSIVE_DEC) || defined(EXIT_DEBUG)
|
||||
static u32 kvmppc_get_dec(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
u64 jd = mftb() - vcpu->arch.dec_jiffies;
|
||||
return vcpu->arch.dec - jd;
|
||||
}
|
||||
#endif
|
||||
|
||||
void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
|
||||
{
|
||||
ulong old_msr = vcpu->arch.msr;
|
||||
|
||||
#ifdef EXIT_DEBUG
|
||||
printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr);
|
||||
#endif
|
||||
msr &= to_book3s(vcpu)->msr_mask;
|
||||
vcpu->arch.msr = msr;
|
||||
vcpu->arch.shadow_msr = msr | MSR_USER32;
|
||||
vcpu->arch.shadow_msr &= ( MSR_VEC | MSR_VSX | MSR_FP | MSR_FE0 |
|
||||
MSR_USER64 | MSR_SE | MSR_BE | MSR_DE |
|
||||
MSR_FE1);
|
||||
|
||||
if (msr & (MSR_WE|MSR_POW)) {
|
||||
if (!vcpu->arch.pending_exceptions) {
|
||||
kvm_vcpu_block(vcpu);
|
||||
vcpu->stat.halt_wakeup++;
|
||||
}
|
||||
}
|
||||
|
||||
if (((vcpu->arch.msr & (MSR_IR|MSR_DR)) != (old_msr & (MSR_IR|MSR_DR))) ||
|
||||
(vcpu->arch.msr & MSR_PR) != (old_msr & MSR_PR)) {
|
||||
kvmppc_mmu_flush_segments(vcpu);
|
||||
kvmppc_mmu_map_segment(vcpu, vcpu->arch.pc);
|
||||
}
|
||||
}
|
||||
|
||||
void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
|
||||
{
|
||||
vcpu->arch.srr0 = vcpu->arch.pc;
|
||||
vcpu->arch.srr1 = vcpu->arch.msr | flags;
|
||||
vcpu->arch.pc = to_book3s(vcpu)->hior + vec;
|
||||
vcpu->arch.mmu.reset_msr(vcpu);
|
||||
}
|
||||
|
||||
void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec)
|
||||
{
|
||||
unsigned int prio;
|
||||
|
||||
vcpu->stat.queue_intr++;
|
||||
switch (vec) {
|
||||
case 0x100: prio = BOOK3S_IRQPRIO_SYSTEM_RESET; break;
|
||||
case 0x200: prio = BOOK3S_IRQPRIO_MACHINE_CHECK; break;
|
||||
case 0x300: prio = BOOK3S_IRQPRIO_DATA_STORAGE; break;
|
||||
case 0x380: prio = BOOK3S_IRQPRIO_DATA_SEGMENT; break;
|
||||
case 0x400: prio = BOOK3S_IRQPRIO_INST_STORAGE; break;
|
||||
case 0x480: prio = BOOK3S_IRQPRIO_INST_SEGMENT; break;
|
||||
case 0x500: prio = BOOK3S_IRQPRIO_EXTERNAL; break;
|
||||
case 0x600: prio = BOOK3S_IRQPRIO_ALIGNMENT; break;
|
||||
case 0x700: prio = BOOK3S_IRQPRIO_PROGRAM; break;
|
||||
case 0x800: prio = BOOK3S_IRQPRIO_FP_UNAVAIL; break;
|
||||
case 0x900: prio = BOOK3S_IRQPRIO_DECREMENTER; break;
|
||||
case 0xc00: prio = BOOK3S_IRQPRIO_SYSCALL; break;
|
||||
case 0xd00: prio = BOOK3S_IRQPRIO_DEBUG; break;
|
||||
case 0xf20: prio = BOOK3S_IRQPRIO_ALTIVEC; break;
|
||||
case 0xf40: prio = BOOK3S_IRQPRIO_VSX; break;
|
||||
default: prio = BOOK3S_IRQPRIO_MAX; break;
|
||||
}
|
||||
|
||||
set_bit(prio, &vcpu->arch.pending_exceptions);
|
||||
#ifdef EXIT_DEBUG
|
||||
printk(KERN_INFO "Queueing interrupt %x\n", vec);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void kvmppc_core_queue_program(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_PROGRAM);
|
||||
}
|
||||
|
||||
void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DECREMENTER);
|
||||
}
|
||||
|
||||
int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return test_bit(BOOK3S_INTERRUPT_DECREMENTER >> 7, &vcpu->arch.pending_exceptions);
|
||||
}
|
||||
|
||||
void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
|
||||
struct kvm_interrupt *irq)
|
||||
{
|
||||
kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL);
|
||||
}
|
||||
|
||||
int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
|
||||
{
|
||||
int deliver = 1;
|
||||
int vec = 0;
|
||||
|
||||
switch (priority) {
|
||||
case BOOK3S_IRQPRIO_DECREMENTER:
|
||||
deliver = vcpu->arch.msr & MSR_EE;
|
||||
vec = BOOK3S_INTERRUPT_DECREMENTER;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_EXTERNAL:
|
||||
deliver = vcpu->arch.msr & MSR_EE;
|
||||
vec = BOOK3S_INTERRUPT_EXTERNAL;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_SYSTEM_RESET:
|
||||
vec = BOOK3S_INTERRUPT_SYSTEM_RESET;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_MACHINE_CHECK:
|
||||
vec = BOOK3S_INTERRUPT_MACHINE_CHECK;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_DATA_STORAGE:
|
||||
vec = BOOK3S_INTERRUPT_DATA_STORAGE;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_INST_STORAGE:
|
||||
vec = BOOK3S_INTERRUPT_INST_STORAGE;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_DATA_SEGMENT:
|
||||
vec = BOOK3S_INTERRUPT_DATA_SEGMENT;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_INST_SEGMENT:
|
||||
vec = BOOK3S_INTERRUPT_INST_SEGMENT;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_ALIGNMENT:
|
||||
vec = BOOK3S_INTERRUPT_ALIGNMENT;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_PROGRAM:
|
||||
vec = BOOK3S_INTERRUPT_PROGRAM;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_VSX:
|
||||
vec = BOOK3S_INTERRUPT_VSX;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_ALTIVEC:
|
||||
vec = BOOK3S_INTERRUPT_ALTIVEC;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_FP_UNAVAIL:
|
||||
vec = BOOK3S_INTERRUPT_FP_UNAVAIL;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_SYSCALL:
|
||||
vec = BOOK3S_INTERRUPT_SYSCALL;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_DEBUG:
|
||||
vec = BOOK3S_INTERRUPT_TRACE;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_PERFORMANCE_MONITOR:
|
||||
vec = BOOK3S_INTERRUPT_PERFMON;
|
||||
break;
|
||||
default:
|
||||
deliver = 0;
|
||||
printk(KERN_ERR "KVM: Unknown interrupt: 0x%x\n", priority);
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
printk(KERN_INFO "Deliver interrupt 0x%x? %x\n", vec, deliver);
|
||||
#endif
|
||||
|
||||
if (deliver)
|
||||
kvmppc_inject_interrupt(vcpu, vec, 0ULL);
|
||||
|
||||
return deliver;
|
||||
}
|
||||
|
||||
void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
unsigned long *pending = &vcpu->arch.pending_exceptions;
|
||||
unsigned int priority;
|
||||
|
||||
/* XXX be more clever here - no need to mftb() on every entry */
|
||||
/* Issue DEC again if it's still active */
|
||||
#ifdef AGGRESSIVE_DEC
|
||||
if (vcpu->arch.msr & MSR_EE)
|
||||
if (kvmppc_get_dec(vcpu) & 0x80000000)
|
||||
kvmppc_core_queue_dec(vcpu);
|
||||
#endif
|
||||
|
||||
#ifdef EXIT_DEBUG
|
||||
if (vcpu->arch.pending_exceptions)
|
||||
printk(KERN_EMERG "KVM: Check pending: %lx\n", vcpu->arch.pending_exceptions);
|
||||
#endif
|
||||
priority = __ffs(*pending);
|
||||
while (priority <= (sizeof(unsigned int) * 8)) {
|
||||
if (kvmppc_book3s_irqprio_deliver(vcpu, priority)) {
|
||||
clear_bit(priority, &vcpu->arch.pending_exceptions);
|
||||
break;
|
||||
}
|
||||
|
||||
priority = find_next_bit(pending,
|
||||
BITS_PER_BYTE * sizeof(*pending),
|
||||
priority + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
|
||||
{
|
||||
vcpu->arch.hflags &= ~BOOK3S_HFLAG_SLB;
|
||||
vcpu->arch.pvr = pvr;
|
||||
if ((pvr >= 0x330000) && (pvr < 0x70330000)) {
|
||||
kvmppc_mmu_book3s_64_init(vcpu);
|
||||
to_book3s(vcpu)->hior = 0xfff00000;
|
||||
to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL;
|
||||
} else {
|
||||
kvmppc_mmu_book3s_32_init(vcpu);
|
||||
to_book3s(vcpu)->hior = 0;
|
||||
to_book3s(vcpu)->msr_mask = 0xffffffffULL;
|
||||
}
|
||||
|
||||
/* If we are in hypervisor level on 970, we can tell the CPU to
|
||||
* treat DCBZ as 32 bytes store */
|
||||
vcpu->arch.hflags &= ~BOOK3S_HFLAG_DCBZ32;
|
||||
if (vcpu->arch.mmu.is_dcbz32(vcpu) && (mfmsr() & MSR_HV) &&
|
||||
!strcmp(cur_cpu_spec->platform, "ppc970"))
|
||||
vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
|
||||
|
||||
}
|
||||
|
||||
/* Book3s_32 CPUs always have 32 bytes cache line size, which Linux assumes. To
|
||||
* make Book3s_32 Linux work on Book3s_64, we have to make sure we trap dcbz to
|
||||
* emulate 32 bytes dcbz length.
|
||||
*
|
||||
* The Book3s_64 inventors also realized this case and implemented a special bit
|
||||
* in the HID5 register, which is a hypervisor ressource. Thus we can't use it.
|
||||
*
|
||||
* My approach here is to patch the dcbz instruction on executing pages.
|
||||
*/
|
||||
static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
|
||||
{
|
||||
bool touched = false;
|
||||
hva_t hpage;
|
||||
u32 *page;
|
||||
int i;
|
||||
|
||||
hpage = gfn_to_hva(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
|
||||
if (kvm_is_error_hva(hpage))
|
||||
return;
|
||||
|
||||
hpage |= pte->raddr & ~PAGE_MASK;
|
||||
hpage &= ~0xFFFULL;
|
||||
|
||||
page = vmalloc(HW_PAGE_SIZE);
|
||||
|
||||
if (copy_from_user(page, (void __user *)hpage, HW_PAGE_SIZE))
|
||||
goto out;
|
||||
|
||||
for (i=0; i < HW_PAGE_SIZE / 4; i++)
|
||||
if ((page[i] & 0xff0007ff) == INS_DCBZ) {
|
||||
page[i] &= 0xfffffff7; // reserved instruction, so we trap
|
||||
touched = true;
|
||||
}
|
||||
|
||||
if (touched)
|
||||
copy_to_user((void __user *)hpage, page, HW_PAGE_SIZE);
|
||||
|
||||
out:
|
||||
vfree(page);
|
||||
}
|
||||
|
||||
static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data,
|
||||
struct kvmppc_pte *pte)
|
||||
{
|
||||
int relocated = (vcpu->arch.msr & (data ? MSR_DR : MSR_IR));
|
||||
int r;
|
||||
|
||||
if (relocated) {
|
||||
r = vcpu->arch.mmu.xlate(vcpu, eaddr, pte, data);
|
||||
} else {
|
||||
pte->eaddr = eaddr;
|
||||
pte->raddr = eaddr & 0xffffffff;
|
||||
pte->vpage = eaddr >> 12;
|
||||
switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
|
||||
case 0:
|
||||
pte->vpage |= VSID_REAL;
|
||||
case MSR_DR:
|
||||
pte->vpage |= VSID_REAL_DR;
|
||||
case MSR_IR:
|
||||
pte->vpage |= VSID_REAL_IR;
|
||||
}
|
||||
pte->may_read = true;
|
||||
pte->may_write = true;
|
||||
pte->may_execute = true;
|
||||
r = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static hva_t kvmppc_bad_hva(void)
|
||||
{
|
||||
return PAGE_OFFSET;
|
||||
}
|
||||
|
||||
static hva_t kvmppc_pte_to_hva(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte,
|
||||
bool read)
|
||||
{
|
||||
hva_t hpage;
|
||||
|
||||
if (read && !pte->may_read)
|
||||
goto err;
|
||||
|
||||
if (!read && !pte->may_write)
|
||||
goto err;
|
||||
|
||||
hpage = gfn_to_hva(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
|
||||
if (kvm_is_error_hva(hpage))
|
||||
goto err;
|
||||
|
||||
return hpage | (pte->raddr & ~PAGE_MASK);
|
||||
err:
|
||||
return kvmppc_bad_hva();
|
||||
}
|
||||
|
||||
int kvmppc_st(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr)
|
||||
{
|
||||
struct kvmppc_pte pte;
|
||||
hva_t hva = eaddr;
|
||||
|
||||
vcpu->stat.st++;
|
||||
|
||||
if (kvmppc_xlate(vcpu, eaddr, false, &pte))
|
||||
goto err;
|
||||
|
||||
hva = kvmppc_pte_to_hva(vcpu, &pte, false);
|
||||
if (kvm_is_error_hva(hva))
|
||||
goto err;
|
||||
|
||||
if (copy_to_user((void __user *)hva, ptr, size)) {
|
||||
printk(KERN_INFO "kvmppc_st at 0x%lx failed\n", hva);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int kvmppc_ld(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr,
|
||||
bool data)
|
||||
{
|
||||
struct kvmppc_pte pte;
|
||||
hva_t hva = eaddr;
|
||||
|
||||
vcpu->stat.ld++;
|
||||
|
||||
if (kvmppc_xlate(vcpu, eaddr, data, &pte))
|
||||
goto err;
|
||||
|
||||
hva = kvmppc_pte_to_hva(vcpu, &pte, true);
|
||||
if (kvm_is_error_hva(hva))
|
||||
goto err;
|
||||
|
||||
if (copy_from_user(ptr, (void __user *)hva, size)) {
|
||||
printk(KERN_INFO "kvmppc_ld at 0x%lx failed\n", hva);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
|
||||
{
|
||||
return kvm_is_visible_gfn(vcpu->kvm, gfn);
|
||||
}
|
||||
|
||||
int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||
ulong eaddr, int vec)
|
||||
{
|
||||
bool data = (vec == BOOK3S_INTERRUPT_DATA_STORAGE);
|
||||
int r = RESUME_GUEST;
|
||||
int relocated;
|
||||
int page_found = 0;
|
||||
struct kvmppc_pte pte;
|
||||
bool is_mmio = false;
|
||||
|
||||
if ( vec == BOOK3S_INTERRUPT_DATA_STORAGE ) {
|
||||
relocated = (vcpu->arch.msr & MSR_DR);
|
||||
} else {
|
||||
relocated = (vcpu->arch.msr & MSR_IR);
|
||||
}
|
||||
|
||||
/* Resolve real address if translation turned on */
|
||||
if (relocated) {
|
||||
page_found = vcpu->arch.mmu.xlate(vcpu, eaddr, &pte, data);
|
||||
} else {
|
||||
pte.may_execute = true;
|
||||
pte.may_read = true;
|
||||
pte.may_write = true;
|
||||
pte.raddr = eaddr & 0xffffffff;
|
||||
pte.eaddr = eaddr;
|
||||
pte.vpage = eaddr >> 12;
|
||||
switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
|
||||
case 0:
|
||||
pte.vpage |= VSID_REAL;
|
||||
case MSR_DR:
|
||||
pte.vpage |= VSID_REAL_DR;
|
||||
case MSR_IR:
|
||||
pte.vpage |= VSID_REAL_IR;
|
||||
}
|
||||
}
|
||||
|
||||
if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
|
||||
(!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) {
|
||||
/*
|
||||
* If we do the dcbz hack, we have to NX on every execution,
|
||||
* so we can patch the executing code. This renders our guest
|
||||
* NX-less.
|
||||
*/
|
||||
pte.may_execute = !data;
|
||||
}
|
||||
|
||||
if (page_found == -ENOENT) {
|
||||
/* Page not found in guest PTE entries */
|
||||
vcpu->arch.dear = vcpu->arch.fault_dear;
|
||||
to_book3s(vcpu)->dsisr = vcpu->arch.fault_dsisr;
|
||||
vcpu->arch.msr |= (vcpu->arch.shadow_msr & 0x00000000f8000000ULL);
|
||||
kvmppc_book3s_queue_irqprio(vcpu, vec);
|
||||
} else if (page_found == -EPERM) {
|
||||
/* Storage protection */
|
||||
vcpu->arch.dear = vcpu->arch.fault_dear;
|
||||
to_book3s(vcpu)->dsisr = vcpu->arch.fault_dsisr & ~DSISR_NOHPTE;
|
||||
to_book3s(vcpu)->dsisr |= DSISR_PROTFAULT;
|
||||
vcpu->arch.msr |= (vcpu->arch.shadow_msr & 0x00000000f8000000ULL);
|
||||
kvmppc_book3s_queue_irqprio(vcpu, vec);
|
||||
} else if (page_found == -EINVAL) {
|
||||
/* Page not found in guest SLB */
|
||||
vcpu->arch.dear = vcpu->arch.fault_dear;
|
||||
kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80);
|
||||
} else if (!is_mmio &&
|
||||
kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) {
|
||||
/* The guest's PTE is not mapped yet. Map on the host */
|
||||
kvmppc_mmu_map_page(vcpu, &pte);
|
||||
if (data)
|
||||
vcpu->stat.sp_storage++;
|
||||
else if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
|
||||
(!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32)))
|
||||
kvmppc_patch_dcbz(vcpu, &pte);
|
||||
} else {
|
||||
/* MMIO */
|
||||
vcpu->stat.mmio_exits++;
|
||||
vcpu->arch.paddr_accessed = pte.raddr;
|
||||
r = kvmppc_emulate_mmio(run, vcpu);
|
||||
if ( r == RESUME_HOST_NV )
|
||||
r = RESUME_HOST;
|
||||
if ( r == RESUME_GUEST_NV )
|
||||
r = RESUME_GUEST;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||
unsigned int exit_nr)
|
||||
{
|
||||
int r = RESUME_HOST;
|
||||
|
||||
vcpu->stat.sum_exits++;
|
||||
|
||||
run->exit_reason = KVM_EXIT_UNKNOWN;
|
||||
run->ready_for_interrupt_injection = 1;
|
||||
#ifdef EXIT_DEBUG
|
||||
printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | dar=0x%lx | dec=0x%x | msr=0x%lx\n",
|
||||
exit_nr, vcpu->arch.pc, vcpu->arch.fault_dear,
|
||||
kvmppc_get_dec(vcpu), vcpu->arch.msr);
|
||||
#elif defined (EXIT_DEBUG_SIMPLE)
|
||||
if ((exit_nr != 0x900) && (exit_nr != 0x500))
|
||||
printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | dar=0x%lx | msr=0x%lx\n",
|
||||
exit_nr, vcpu->arch.pc, vcpu->arch.fault_dear,
|
||||
vcpu->arch.msr);
|
||||
#endif
|
||||
kvm_resched(vcpu);
|
||||
switch (exit_nr) {
|
||||
case BOOK3S_INTERRUPT_INST_STORAGE:
|
||||
vcpu->stat.pf_instruc++;
|
||||
/* only care about PTEG not found errors, but leave NX alone */
|
||||
if (vcpu->arch.shadow_msr & 0x40000000) {
|
||||
r = kvmppc_handle_pagefault(run, vcpu, vcpu->arch.pc, exit_nr);
|
||||
vcpu->stat.sp_instruc++;
|
||||
} else if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
|
||||
(!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) {
|
||||
/*
|
||||
* XXX If we do the dcbz hack we use the NX bit to flush&patch the page,
|
||||
* so we can't use the NX bit inside the guest. Let's cross our fingers,
|
||||
* that no guest that needs the dcbz hack does NX.
|
||||
*/
|
||||
kvmppc_mmu_pte_flush(vcpu, vcpu->arch.pc, ~0xFFFULL);
|
||||
} else {
|
||||
vcpu->arch.msr |= (vcpu->arch.shadow_msr & 0x58000000);
|
||||
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
|
||||
kvmppc_mmu_pte_flush(vcpu, vcpu->arch.pc, ~0xFFFULL);
|
||||
r = RESUME_GUEST;
|
||||
}
|
||||
break;
|
||||
case BOOK3S_INTERRUPT_DATA_STORAGE:
|
||||
vcpu->stat.pf_storage++;
|
||||
/* The only case we need to handle is missing shadow PTEs */
|
||||
if (vcpu->arch.fault_dsisr & DSISR_NOHPTE) {
|
||||
r = kvmppc_handle_pagefault(run, vcpu, vcpu->arch.fault_dear, exit_nr);
|
||||
} else {
|
||||
vcpu->arch.dear = vcpu->arch.fault_dear;
|
||||
to_book3s(vcpu)->dsisr = vcpu->arch.fault_dsisr;
|
||||
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
|
||||
kvmppc_mmu_pte_flush(vcpu, vcpu->arch.dear, ~0xFFFULL);
|
||||
r = RESUME_GUEST;
|
||||
}
|
||||
break;
|
||||
case BOOK3S_INTERRUPT_DATA_SEGMENT:
|
||||
if (kvmppc_mmu_map_segment(vcpu, vcpu->arch.fault_dear) < 0) {
|
||||
vcpu->arch.dear = vcpu->arch.fault_dear;
|
||||
kvmppc_book3s_queue_irqprio(vcpu,
|
||||
BOOK3S_INTERRUPT_DATA_SEGMENT);
|
||||
}
|
||||
r = RESUME_GUEST;
|
||||
break;
|
||||
case BOOK3S_INTERRUPT_INST_SEGMENT:
|
||||
if (kvmppc_mmu_map_segment(vcpu, vcpu->arch.pc) < 0) {
|
||||
kvmppc_book3s_queue_irqprio(vcpu,
|
||||
BOOK3S_INTERRUPT_INST_SEGMENT);
|
||||
}
|
||||
r = RESUME_GUEST;
|
||||
break;
|
||||
/* We're good on these - the host merely wanted to get our attention */
|
||||
case BOOK3S_INTERRUPT_DECREMENTER:
|
||||
vcpu->stat.dec_exits++;
|
||||
r = RESUME_GUEST;
|
||||
break;
|
||||
case BOOK3S_INTERRUPT_EXTERNAL:
|
||||
vcpu->stat.ext_intr_exits++;
|
||||
r = RESUME_GUEST;
|
||||
break;
|
||||
case BOOK3S_INTERRUPT_PROGRAM:
|
||||
{
|
||||
enum emulation_result er;
|
||||
|
||||
if (vcpu->arch.msr & MSR_PR) {
|
||||
#ifdef EXIT_DEBUG
|
||||
printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", vcpu->arch.pc, vcpu->arch.last_inst);
|
||||
#endif
|
||||
if ((vcpu->arch.last_inst & 0xff0007ff) !=
|
||||
(INS_DCBZ & 0xfffffff7)) {
|
||||
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
|
||||
r = RESUME_GUEST;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vcpu->stat.emulated_inst_exits++;
|
||||
er = kvmppc_emulate_instruction(run, vcpu);
|
||||
switch (er) {
|
||||
case EMULATE_DONE:
|
||||
r = RESUME_GUEST;
|
||||
break;
|
||||
case EMULATE_FAIL:
|
||||
printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
|
||||
__func__, vcpu->arch.pc, vcpu->arch.last_inst);
|
||||
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
|
||||
r = RESUME_GUEST;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BOOK3S_INTERRUPT_SYSCALL:
|
||||
#ifdef EXIT_DEBUG
|
||||
printk(KERN_INFO "Syscall Nr %d\n", (int)vcpu->arch.gpr[0]);
|
||||
#endif
|
||||
vcpu->stat.syscall_exits++;
|
||||
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
|
||||
r = RESUME_GUEST;
|
||||
break;
|
||||
case BOOK3S_INTERRUPT_MACHINE_CHECK:
|
||||
case BOOK3S_INTERRUPT_FP_UNAVAIL:
|
||||
case BOOK3S_INTERRUPT_TRACE:
|
||||
case BOOK3S_INTERRUPT_ALTIVEC:
|
||||
case BOOK3S_INTERRUPT_VSX:
|
||||
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
|
||||
r = RESUME_GUEST;
|
||||
break;
|
||||
default:
|
||||
/* Ugh - bork here! What did we get? */
|
||||
printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | msr=0x%lx\n", exit_nr, vcpu->arch.pc, vcpu->arch.shadow_msr);
|
||||
r = RESUME_HOST;
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (!(r & RESUME_HOST)) {
|
||||
/* To avoid clobbering exit_reason, only check for signals if
|
||||
* we aren't already exiting to userspace for some other
|
||||
* reason. */
|
||||
if (signal_pending(current)) {
|
||||
#ifdef EXIT_DEBUG
|
||||
printk(KERN_EMERG "KVM: Going back to host\n");
|
||||
#endif
|
||||
vcpu->stat.signal_exits++;
|
||||
run->exit_reason = KVM_EXIT_INTR;
|
||||
r = -EINTR;
|
||||
} else {
|
||||
/* In case an interrupt came in that was triggered
|
||||
* from userspace (like DEC), we need to check what
|
||||
* to inject now! */
|
||||
kvmppc_core_deliver_interrupts(vcpu);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EXIT_DEBUG
|
||||
printk(KERN_EMERG "KVM exit: vcpu=0x%p pc=0x%lx r=0x%x\n", vcpu, vcpu->arch.pc, r);
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
|
||||
{
|
||||
int i;
|
||||
|
||||
regs->pc = vcpu->arch.pc;
|
||||
regs->cr = vcpu->arch.cr;
|
||||
regs->ctr = vcpu->arch.ctr;
|
||||
regs->lr = vcpu->arch.lr;
|
||||
regs->xer = vcpu->arch.xer;
|
||||
regs->msr = vcpu->arch.msr;
|
||||
regs->srr0 = vcpu->arch.srr0;
|
||||
regs->srr1 = vcpu->arch.srr1;
|
||||
regs->pid = vcpu->arch.pid;
|
||||
regs->sprg0 = vcpu->arch.sprg0;
|
||||
regs->sprg1 = vcpu->arch.sprg1;
|
||||
regs->sprg2 = vcpu->arch.sprg2;
|
||||
regs->sprg3 = vcpu->arch.sprg3;
|
||||
regs->sprg5 = vcpu->arch.sprg4;
|
||||
regs->sprg6 = vcpu->arch.sprg5;
|
||||
regs->sprg7 = vcpu->arch.sprg6;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
|
||||
regs->gpr[i] = vcpu->arch.gpr[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
|
||||
{
|
||||
int i;
|
||||
|
||||
vcpu->arch.pc = regs->pc;
|
||||
vcpu->arch.cr = regs->cr;
|
||||
vcpu->arch.ctr = regs->ctr;
|
||||
vcpu->arch.lr = regs->lr;
|
||||
vcpu->arch.xer = regs->xer;
|
||||
kvmppc_set_msr(vcpu, regs->msr);
|
||||
vcpu->arch.srr0 = regs->srr0;
|
||||
vcpu->arch.srr1 = regs->srr1;
|
||||
vcpu->arch.sprg0 = regs->sprg0;
|
||||
vcpu->arch.sprg1 = regs->sprg1;
|
||||
vcpu->arch.sprg2 = regs->sprg2;
|
||||
vcpu->arch.sprg3 = regs->sprg3;
|
||||
vcpu->arch.sprg5 = regs->sprg4;
|
||||
vcpu->arch.sprg6 = regs->sprg5;
|
||||
vcpu->arch.sprg7 = regs->sprg6;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(vcpu->arch.gpr); i++)
|
||||
vcpu->arch.gpr[i] = regs->gpr[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
|
||||
struct kvm_sregs *sregs)
|
||||
{
|
||||
struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
|
||||
int i;
|
||||
|
||||
sregs->pvr = vcpu->arch.pvr;
|
||||
|
||||
sregs->u.s.sdr1 = to_book3s(vcpu)->sdr1;
|
||||
if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) {
|
||||
for (i = 0; i < 64; i++) {
|
||||
sregs->u.s.ppc64.slb[i].slbe = vcpu3s->slb[i].orige | i;
|
||||
sregs->u.s.ppc64.slb[i].slbv = vcpu3s->slb[i].origv;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < 16; i++) {
|
||||
sregs->u.s.ppc32.sr[i] = vcpu3s->sr[i].raw;
|
||||
sregs->u.s.ppc32.sr[i] = vcpu3s->sr[i].raw;
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
sregs->u.s.ppc32.ibat[i] = vcpu3s->ibat[i].raw;
|
||||
sregs->u.s.ppc32.dbat[i] = vcpu3s->dbat[i].raw;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
|
||||
struct kvm_sregs *sregs)
|
||||
{
|
||||
struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
|
||||
int i;
|
||||
|
||||
kvmppc_set_pvr(vcpu, sregs->pvr);
|
||||
|
||||
vcpu3s->sdr1 = sregs->u.s.sdr1;
|
||||
if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) {
|
||||
for (i = 0; i < 64; i++) {
|
||||
vcpu->arch.mmu.slbmte(vcpu, sregs->u.s.ppc64.slb[i].slbv,
|
||||
sregs->u.s.ppc64.slb[i].slbe);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < 16; i++) {
|
||||
vcpu->arch.mmu.mtsrin(vcpu, i, sregs->u.s.ppc32.sr[i]);
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), false,
|
||||
(u32)sregs->u.s.ppc32.ibat[i]);
|
||||
kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), true,
|
||||
(u32)(sregs->u.s.ppc32.ibat[i] >> 32));
|
||||
kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), false,
|
||||
(u32)sregs->u.s.ppc32.dbat[i]);
|
||||
kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), true,
|
||||
(u32)(sregs->u.s.ppc32.dbat[i] >> 32));
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush the MMU after messing with the segments */
|
||||
kvmppc_mmu_pte_flush(vcpu, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
|
||||
struct kvm_translation *tr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get (and clear) the dirty memory log for a memory slot.
|
||||
*/
|
||||
int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
|
||||
struct kvm_dirty_log *log)
|
||||
{
|
||||
struct kvm_memory_slot *memslot;
|
||||
struct kvm_vcpu *vcpu;
|
||||
ulong ga, ga_end;
|
||||
int is_dirty = 0;
|
||||
int r, n;
|
||||
|
||||
down_write(&kvm->slots_lock);
|
||||
|
||||
r = kvm_get_dirty_log(kvm, log, &is_dirty);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
/* If nothing is dirty, don't bother messing with page tables. */
|
||||
if (is_dirty) {
|
||||
memslot = &kvm->memslots[log->slot];
|
||||
|
||||
ga = memslot->base_gfn << PAGE_SHIFT;
|
||||
ga_end = ga + (memslot->npages << PAGE_SHIFT);
|
||||
|
||||
kvm_for_each_vcpu(n, vcpu, kvm)
|
||||
kvmppc_mmu_pte_pflush(vcpu, ga, ga_end);
|
||||
|
||||
n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
|
||||
memset(memslot->dirty_bitmap, 0, n);
|
||||
}
|
||||
|
||||
r = 0;
|
||||
out:
|
||||
up_write(&kvm->slots_lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
int kvmppc_core_check_processor_compat(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
|
||||
{
|
||||
struct kvmppc_vcpu_book3s *vcpu_book3s;
|
||||
struct kvm_vcpu *vcpu;
|
||||
int err;
|
||||
|
||||
vcpu_book3s = (struct kvmppc_vcpu_book3s *)__get_free_pages( GFP_KERNEL | __GFP_ZERO,
|
||||
get_order(sizeof(struct kvmppc_vcpu_book3s)));
|
||||
if (!vcpu_book3s) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
vcpu = &vcpu_book3s->vcpu;
|
||||
err = kvm_vcpu_init(vcpu, kvm, id);
|
||||
if (err)
|
||||
goto free_vcpu;
|
||||
|
||||
vcpu->arch.host_retip = kvm_return_point;
|
||||
vcpu->arch.host_msr = mfmsr();
|
||||
/* default to book3s_64 (970fx) */
|
||||
vcpu->arch.pvr = 0x3C0301;
|
||||
kvmppc_set_pvr(vcpu, vcpu->arch.pvr);
|
||||
vcpu_book3s->slb_nr = 64;
|
||||
|
||||
/* remember where some real-mode handlers are */
|
||||
vcpu->arch.trampoline_lowmem = kvmppc_trampoline_lowmem;
|
||||
vcpu->arch.trampoline_enter = kvmppc_trampoline_enter;
|
||||
vcpu->arch.highmem_handler = (ulong)kvmppc_handler_highmem;
|
||||
|
||||
vcpu->arch.shadow_msr = MSR_USER64;
|
||||
|
||||
err = __init_new_context();
|
||||
if (err < 0)
|
||||
goto free_vcpu;
|
||||
vcpu_book3s->context_id = err;
|
||||
|
||||
vcpu_book3s->vsid_max = ((vcpu_book3s->context_id + 1) << USER_ESID_BITS) - 1;
|
||||
vcpu_book3s->vsid_first = vcpu_book3s->context_id << USER_ESID_BITS;
|
||||
vcpu_book3s->vsid_next = vcpu_book3s->vsid_first;
|
||||
|
||||
return vcpu;
|
||||
|
||||
free_vcpu:
|
||||
free_pages((long)vcpu_book3s, get_order(sizeof(struct kvmppc_vcpu_book3s)));
|
||||
out:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
|
||||
|
||||
__destroy_context(vcpu_book3s->context_id);
|
||||
kvm_vcpu_uninit(vcpu);
|
||||
free_pages((long)vcpu_book3s, get_order(sizeof(struct kvmppc_vcpu_book3s)));
|
||||
}
|
||||
|
||||
extern int __kvmppc_vcpu_entry(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
|
||||
int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* No need to go into the guest when all we do is going out */
|
||||
if (signal_pending(current)) {
|
||||
kvm_run->exit_reason = KVM_EXIT_INTR;
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
/* XXX we get called with irq disabled - change that! */
|
||||
local_irq_enable();
|
||||
|
||||
ret = __kvmppc_vcpu_entry(kvm_run, vcpu);
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kvmppc_book3s_init(void)
|
||||
{
|
||||
return kvm_init(NULL, sizeof(struct kvmppc_vcpu_book3s), THIS_MODULE);
|
||||
}
|
||||
|
||||
static void kvmppc_book3s_exit(void)
|
||||
{
|
||||
kvm_exit();
|
||||
}
|
||||
|
||||
module_init(kvmppc_book3s_init);
|
||||
module_exit(kvmppc_book3s_exit);
|
372
arch/powerpc/kvm/book3s_32_mmu.c
Normal file
372
arch/powerpc/kvm/book3s_32_mmu.c
Normal file
|
@ -0,0 +1,372 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright SUSE Linux Products GmbH 2009
|
||||
*
|
||||
* Authors: Alexander Graf <agraf@suse.de>
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kvm.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/highmem.h>
|
||||
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/kvm_ppc.h>
|
||||
#include <asm/kvm_book3s.h>
|
||||
|
||||
/* #define DEBUG_MMU */
|
||||
/* #define DEBUG_MMU_PTE */
|
||||
/* #define DEBUG_MMU_PTE_IP 0xfff14c40 */
|
||||
|
||||
#ifdef DEBUG_MMU
|
||||
#define dprintk(X...) printk(KERN_INFO X)
|
||||
#else
|
||||
#define dprintk(X...) do { } while(0)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_PTE
|
||||
#define dprintk_pte(X...) printk(KERN_INFO X)
|
||||
#else
|
||||
#define dprintk_pte(X...) do { } while(0)
|
||||
#endif
|
||||
|
||||
#define PTEG_FLAG_ACCESSED 0x00000100
|
||||
#define PTEG_FLAG_DIRTY 0x00000080
|
||||
|
||||
static inline bool check_debug_ip(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
#ifdef DEBUG_MMU_PTE_IP
|
||||
return vcpu->arch.pc == DEBUG_MMU_PTE_IP;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr,
|
||||
struct kvmppc_pte *pte, bool data);
|
||||
|
||||
static struct kvmppc_sr *find_sr(struct kvmppc_vcpu_book3s *vcpu_book3s, gva_t eaddr)
|
||||
{
|
||||
return &vcpu_book3s->sr[(eaddr >> 28) & 0xf];
|
||||
}
|
||||
|
||||
static u64 kvmppc_mmu_book3s_32_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr,
|
||||
bool data)
|
||||
{
|
||||
struct kvmppc_sr *sre = find_sr(to_book3s(vcpu), eaddr);
|
||||
struct kvmppc_pte pte;
|
||||
|
||||
if (!kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, &pte, data))
|
||||
return pte.vpage;
|
||||
|
||||
return (((u64)eaddr >> 12) & 0xffff) | (((u64)sre->vsid) << 16);
|
||||
}
|
||||
|
||||
static void kvmppc_mmu_book3s_32_reset_msr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
kvmppc_set_msr(vcpu, 0);
|
||||
}
|
||||
|
||||
static hva_t kvmppc_mmu_book3s_32_get_pteg(struct kvmppc_vcpu_book3s *vcpu_book3s,
|
||||
struct kvmppc_sr *sre, gva_t eaddr,
|
||||
bool primary)
|
||||
{
|
||||
u32 page, hash, pteg, htabmask;
|
||||
hva_t r;
|
||||
|
||||
page = (eaddr & 0x0FFFFFFF) >> 12;
|
||||
htabmask = ((vcpu_book3s->sdr1 & 0x1FF) << 16) | 0xFFC0;
|
||||
|
||||
hash = ((sre->vsid ^ page) << 6);
|
||||
if (!primary)
|
||||
hash = ~hash;
|
||||
hash &= htabmask;
|
||||
|
||||
pteg = (vcpu_book3s->sdr1 & 0xffff0000) | hash;
|
||||
|
||||
dprintk("MMU: pc=0x%lx eaddr=0x%lx sdr1=0x%llx pteg=0x%x vsid=0x%x\n",
|
||||
vcpu_book3s->vcpu.arch.pc, eaddr, vcpu_book3s->sdr1, pteg,
|
||||
sre->vsid);
|
||||
|
||||
r = gfn_to_hva(vcpu_book3s->vcpu.kvm, pteg >> PAGE_SHIFT);
|
||||
if (kvm_is_error_hva(r))
|
||||
return r;
|
||||
return r | (pteg & ~PAGE_MASK);
|
||||
}
|
||||
|
||||
static u32 kvmppc_mmu_book3s_32_get_ptem(struct kvmppc_sr *sre, gva_t eaddr,
|
||||
bool primary)
|
||||
{
|
||||
return ((eaddr & 0x0fffffff) >> 22) | (sre->vsid << 7) |
|
||||
(primary ? 0 : 0x40) | 0x80000000;
|
||||
}
|
||||
|
||||
static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr,
|
||||
struct kvmppc_pte *pte, bool data)
|
||||
{
|
||||
struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
|
||||
struct kvmppc_bat *bat;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (data)
|
||||
bat = &vcpu_book3s->dbat[i];
|
||||
else
|
||||
bat = &vcpu_book3s->ibat[i];
|
||||
|
||||
if (vcpu->arch.msr & MSR_PR) {
|
||||
if (!bat->vp)
|
||||
continue;
|
||||
} else {
|
||||
if (!bat->vs)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (check_debug_ip(vcpu))
|
||||
{
|
||||
dprintk_pte("%cBAT %02d: 0x%lx - 0x%x (0x%x)\n",
|
||||
data ? 'd' : 'i', i, eaddr, bat->bepi,
|
||||
bat->bepi_mask);
|
||||
}
|
||||
if ((eaddr & bat->bepi_mask) == bat->bepi) {
|
||||
pte->raddr = bat->brpn | (eaddr & ~bat->bepi_mask);
|
||||
pte->vpage = (eaddr >> 12) | VSID_BAT;
|
||||
pte->may_read = bat->pp;
|
||||
pte->may_write = bat->pp > 1;
|
||||
pte->may_execute = true;
|
||||
if (!pte->may_read) {
|
||||
printk(KERN_INFO "BAT is not readable!\n");
|
||||
continue;
|
||||
}
|
||||
if (!pte->may_write) {
|
||||
/* let's treat r/o BATs as not-readable for now */
|
||||
dprintk_pte("BAT is read-only!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr,
|
||||
struct kvmppc_pte *pte, bool data,
|
||||
bool primary)
|
||||
{
|
||||
struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
|
||||
struct kvmppc_sr *sre;
|
||||
hva_t ptegp;
|
||||
u32 pteg[16];
|
||||
u64 ptem = 0;
|
||||
int i;
|
||||
int found = 0;
|
||||
|
||||
sre = find_sr(vcpu_book3s, eaddr);
|
||||
|
||||
dprintk_pte("SR 0x%lx: vsid=0x%x, raw=0x%x\n", eaddr >> 28,
|
||||
sre->vsid, sre->raw);
|
||||
|
||||
pte->vpage = kvmppc_mmu_book3s_32_ea_to_vp(vcpu, eaddr, data);
|
||||
|
||||
ptegp = kvmppc_mmu_book3s_32_get_pteg(vcpu_book3s, sre, eaddr, primary);
|
||||
if (kvm_is_error_hva(ptegp)) {
|
||||
printk(KERN_INFO "KVM: Invalid PTEG!\n");
|
||||
goto no_page_found;
|
||||
}
|
||||
|
||||
ptem = kvmppc_mmu_book3s_32_get_ptem(sre, eaddr, primary);
|
||||
|
||||
if(copy_from_user(pteg, (void __user *)ptegp, sizeof(pteg))) {
|
||||
printk(KERN_ERR "KVM: Can't copy data from 0x%lx!\n", ptegp);
|
||||
goto no_page_found;
|
||||
}
|
||||
|
||||
for (i=0; i<16; i+=2) {
|
||||
if (ptem == pteg[i]) {
|
||||
u8 pp;
|
||||
|
||||
pte->raddr = (pteg[i+1] & ~(0xFFFULL)) | (eaddr & 0xFFF);
|
||||
pp = pteg[i+1] & 3;
|
||||
|
||||
if ((sre->Kp && (vcpu->arch.msr & MSR_PR)) ||
|
||||
(sre->Ks && !(vcpu->arch.msr & MSR_PR)))
|
||||
pp |= 4;
|
||||
|
||||
pte->may_write = false;
|
||||
pte->may_read = false;
|
||||
pte->may_execute = true;
|
||||
switch (pp) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 6:
|
||||
pte->may_write = true;
|
||||
case 3:
|
||||
case 5:
|
||||
case 7:
|
||||
pte->may_read = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !pte->may_read )
|
||||
continue;
|
||||
|
||||
dprintk_pte("MMU: Found PTE -> %x %x - %x\n",
|
||||
pteg[i], pteg[i+1], pp);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update PTE C and A bits, so the guest's swapper knows we used the
|
||||
page */
|
||||
if (found) {
|
||||
u32 oldpte = pteg[i+1];
|
||||
|
||||
if (pte->may_read)
|
||||
pteg[i+1] |= PTEG_FLAG_ACCESSED;
|
||||
if (pte->may_write)
|
||||
pteg[i+1] |= PTEG_FLAG_DIRTY;
|
||||
else
|
||||
dprintk_pte("KVM: Mapping read-only page!\n");
|
||||
|
||||
/* Write back into the PTEG */
|
||||
if (pteg[i+1] != oldpte)
|
||||
copy_to_user((void __user *)ptegp, pteg, sizeof(pteg));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
no_page_found:
|
||||
|
||||
if (check_debug_ip(vcpu)) {
|
||||
dprintk_pte("KVM MMU: No PTE found (sdr1=0x%llx ptegp=0x%lx)\n",
|
||||
to_book3s(vcpu)->sdr1, ptegp);
|
||||
for (i=0; i<16; i+=2) {
|
||||
dprintk_pte(" %02d: 0x%x - 0x%x (0x%llx)\n",
|
||||
i, pteg[i], pteg[i+1], ptem);
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
|
||||
struct kvmppc_pte *pte, bool data)
|
||||
{
|
||||
int r;
|
||||
|
||||
pte->eaddr = eaddr;
|
||||
r = kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, pte, data);
|
||||
if (r < 0)
|
||||
r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, data, true);
|
||||
if (r < 0)
|
||||
r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, data, false);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static u32 kvmppc_mmu_book3s_32_mfsrin(struct kvm_vcpu *vcpu, u32 srnum)
|
||||
{
|
||||
return to_book3s(vcpu)->sr[srnum].raw;
|
||||
}
|
||||
|
||||
static void kvmppc_mmu_book3s_32_mtsrin(struct kvm_vcpu *vcpu, u32 srnum,
|
||||
ulong value)
|
||||
{
|
||||
struct kvmppc_sr *sre;
|
||||
|
||||
sre = &to_book3s(vcpu)->sr[srnum];
|
||||
|
||||
/* Flush any left-over shadows from the previous SR */
|
||||
|
||||
/* XXX Not necessary? */
|
||||
/* kvmppc_mmu_pte_flush(vcpu, ((u64)sre->vsid) << 28, 0xf0000000ULL); */
|
||||
|
||||
/* And then put in the new SR */
|
||||
sre->raw = value;
|
||||
sre->vsid = (value & 0x0fffffff);
|
||||
sre->Ks = (value & 0x40000000) ? true : false;
|
||||
sre->Kp = (value & 0x20000000) ? true : false;
|
||||
sre->nx = (value & 0x10000000) ? true : false;
|
||||
|
||||
/* Map the new segment */
|
||||
kvmppc_mmu_map_segment(vcpu, srnum << SID_SHIFT);
|
||||
}
|
||||
|
||||
static void kvmppc_mmu_book3s_32_tlbie(struct kvm_vcpu *vcpu, ulong ea, bool large)
|
||||
{
|
||||
kvmppc_mmu_pte_flush(vcpu, ea, ~0xFFFULL);
|
||||
}
|
||||
|
||||
static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, u64 esid,
|
||||
u64 *vsid)
|
||||
{
|
||||
/* In case we only have one of MSR_IR or MSR_DR set, let's put
|
||||
that in the real-mode context (and hope RM doesn't access
|
||||
high memory) */
|
||||
switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
|
||||
case 0:
|
||||
*vsid = (VSID_REAL >> 16) | esid;
|
||||
break;
|
||||
case MSR_IR:
|
||||
*vsid = (VSID_REAL_IR >> 16) | esid;
|
||||
break;
|
||||
case MSR_DR:
|
||||
*vsid = (VSID_REAL_DR >> 16) | esid;
|
||||
break;
|
||||
case MSR_DR|MSR_IR:
|
||||
{
|
||||
ulong ea;
|
||||
ea = esid << SID_SHIFT;
|
||||
*vsid = find_sr(to_book3s(vcpu), ea)->vsid;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool kvmppc_mmu_book3s_32_is_dcbz32(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvmppc_mmu *mmu = &vcpu->arch.mmu;
|
||||
|
||||
mmu->mtsrin = kvmppc_mmu_book3s_32_mtsrin;
|
||||
mmu->mfsrin = kvmppc_mmu_book3s_32_mfsrin;
|
||||
mmu->xlate = kvmppc_mmu_book3s_32_xlate;
|
||||
mmu->reset_msr = kvmppc_mmu_book3s_32_reset_msr;
|
||||
mmu->tlbie = kvmppc_mmu_book3s_32_tlbie;
|
||||
mmu->esid_to_vsid = kvmppc_mmu_book3s_32_esid_to_vsid;
|
||||
mmu->ea_to_vp = kvmppc_mmu_book3s_32_ea_to_vp;
|
||||
mmu->is_dcbz32 = kvmppc_mmu_book3s_32_is_dcbz32;
|
||||
|
||||
mmu->slbmte = NULL;
|
||||
mmu->slbmfee = NULL;
|
||||
mmu->slbmfev = NULL;
|
||||
mmu->slbie = NULL;
|
||||
mmu->slbia = NULL;
|
||||
}
|
345
arch/powerpc/kvm/book3s_64_emulate.c
Normal file
345
arch/powerpc/kvm/book3s_64_emulate.c
Normal file
|
@ -0,0 +1,345 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright SUSE Linux Products GmbH 2009
|
||||
*
|
||||
* Authors: Alexander Graf <agraf@suse.de>
|
||||
*/
|
||||
|
||||
#include <asm/kvm_ppc.h>
|
||||
#include <asm/disassemble.h>
|
||||
#include <asm/kvm_book3s.h>
|
||||
#include <asm/reg.h>
|
||||
|
||||
#define OP_19_XOP_RFID 18
|
||||
#define OP_19_XOP_RFI 50
|
||||
|
||||
#define OP_31_XOP_MFMSR 83
|
||||
#define OP_31_XOP_MTMSR 146
|
||||
#define OP_31_XOP_MTMSRD 178
|
||||
#define OP_31_XOP_MTSRIN 242
|
||||
#define OP_31_XOP_TLBIEL 274
|
||||
#define OP_31_XOP_TLBIE 306
|
||||
#define OP_31_XOP_SLBMTE 402
|
||||
#define OP_31_XOP_SLBIE 434
|
||||
#define OP_31_XOP_SLBIA 498
|
||||
#define OP_31_XOP_MFSRIN 659
|
||||
#define OP_31_XOP_SLBMFEV 851
|
||||
#define OP_31_XOP_EIOIO 854
|
||||
#define OP_31_XOP_SLBMFEE 915
|
||||
|
||||
/* DCBZ is actually 1014, but we patch it to 1010 so we get a trap */
|
||||
#define OP_31_XOP_DCBZ 1010
|
||||
|
||||
int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||
unsigned int inst, int *advance)
|
||||
{
|
||||
int emulated = EMULATE_DONE;
|
||||
|
||||
switch (get_op(inst)) {
|
||||
case 19:
|
||||
switch (get_xop(inst)) {
|
||||
case OP_19_XOP_RFID:
|
||||
case OP_19_XOP_RFI:
|
||||
vcpu->arch.pc = vcpu->arch.srr0;
|
||||
kvmppc_set_msr(vcpu, vcpu->arch.srr1);
|
||||
*advance = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
emulated = EMULATE_FAIL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 31:
|
||||
switch (get_xop(inst)) {
|
||||
case OP_31_XOP_MFMSR:
|
||||
vcpu->arch.gpr[get_rt(inst)] = vcpu->arch.msr;
|
||||
break;
|
||||
case OP_31_XOP_MTMSRD:
|
||||
{
|
||||
ulong rs = vcpu->arch.gpr[get_rs(inst)];
|
||||
if (inst & 0x10000) {
|
||||
vcpu->arch.msr &= ~(MSR_RI | MSR_EE);
|
||||
vcpu->arch.msr |= rs & (MSR_RI | MSR_EE);
|
||||
} else
|
||||
kvmppc_set_msr(vcpu, rs);
|
||||
break;
|
||||
}
|
||||
case OP_31_XOP_MTMSR:
|
||||
kvmppc_set_msr(vcpu, vcpu->arch.gpr[get_rs(inst)]);
|
||||
break;
|
||||
case OP_31_XOP_MFSRIN:
|
||||
{
|
||||
int srnum;
|
||||
|
||||
srnum = (vcpu->arch.gpr[get_rb(inst)] >> 28) & 0xf;
|
||||
if (vcpu->arch.mmu.mfsrin) {
|
||||
u32 sr;
|
||||
sr = vcpu->arch.mmu.mfsrin(vcpu, srnum);
|
||||
vcpu->arch.gpr[get_rt(inst)] = sr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_31_XOP_MTSRIN:
|
||||
vcpu->arch.mmu.mtsrin(vcpu,
|
||||
(vcpu->arch.gpr[get_rb(inst)] >> 28) & 0xf,
|
||||
vcpu->arch.gpr[get_rs(inst)]);
|
||||
break;
|
||||
case OP_31_XOP_TLBIE:
|
||||
case OP_31_XOP_TLBIEL:
|
||||
{
|
||||
bool large = (inst & 0x00200000) ? true : false;
|
||||
ulong addr = vcpu->arch.gpr[get_rb(inst)];
|
||||
vcpu->arch.mmu.tlbie(vcpu, addr, large);
|
||||
break;
|
||||
}
|
||||
case OP_31_XOP_EIOIO:
|
||||
break;
|
||||
case OP_31_XOP_SLBMTE:
|
||||
if (!vcpu->arch.mmu.slbmte)
|
||||
return EMULATE_FAIL;
|
||||
|
||||
vcpu->arch.mmu.slbmte(vcpu, vcpu->arch.gpr[get_rs(inst)],
|
||||
vcpu->arch.gpr[get_rb(inst)]);
|
||||
break;
|
||||
case OP_31_XOP_SLBIE:
|
||||
if (!vcpu->arch.mmu.slbie)
|
||||
return EMULATE_FAIL;
|
||||
|
||||
vcpu->arch.mmu.slbie(vcpu, vcpu->arch.gpr[get_rb(inst)]);
|
||||
break;
|
||||
case OP_31_XOP_SLBIA:
|
||||
if (!vcpu->arch.mmu.slbia)
|
||||
return EMULATE_FAIL;
|
||||
|
||||
vcpu->arch.mmu.slbia(vcpu);
|
||||
break;
|
||||
case OP_31_XOP_SLBMFEE:
|
||||
if (!vcpu->arch.mmu.slbmfee) {
|
||||
emulated = EMULATE_FAIL;
|
||||
} else {
|
||||
ulong t, rb;
|
||||
|
||||
rb = vcpu->arch.gpr[get_rb(inst)];
|
||||
t = vcpu->arch.mmu.slbmfee(vcpu, rb);
|
||||
vcpu->arch.gpr[get_rt(inst)] = t;
|
||||
}
|
||||
break;
|
||||
case OP_31_XOP_SLBMFEV:
|
||||
if (!vcpu->arch.mmu.slbmfev) {
|
||||
emulated = EMULATE_FAIL;
|
||||
} else {
|
||||
ulong t, rb;
|
||||
|
||||
rb = vcpu->arch.gpr[get_rb(inst)];
|
||||
t = vcpu->arch.mmu.slbmfev(vcpu, rb);
|
||||
vcpu->arch.gpr[get_rt(inst)] = t;
|
||||
}
|
||||
break;
|
||||
case OP_31_XOP_DCBZ:
|
||||
{
|
||||
ulong rb = vcpu->arch.gpr[get_rb(inst)];
|
||||
ulong ra = 0;
|
||||
ulong addr;
|
||||
u32 zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
if (get_ra(inst))
|
||||
ra = vcpu->arch.gpr[get_ra(inst)];
|
||||
|
||||
addr = (ra + rb) & ~31ULL;
|
||||
if (!(vcpu->arch.msr & MSR_SF))
|
||||
addr &= 0xffffffff;
|
||||
|
||||
if (kvmppc_st(vcpu, addr, 32, zeros)) {
|
||||
vcpu->arch.dear = addr;
|
||||
vcpu->arch.fault_dear = addr;
|
||||
to_book3s(vcpu)->dsisr = DSISR_PROTFAULT |
|
||||
DSISR_ISSTORE;
|
||||
kvmppc_book3s_queue_irqprio(vcpu,
|
||||
BOOK3S_INTERRUPT_DATA_STORAGE);
|
||||
kvmppc_mmu_pte_flush(vcpu, addr, ~0xFFFULL);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
emulated = EMULATE_FAIL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
emulated = EMULATE_FAIL;
|
||||
}
|
||||
|
||||
return emulated;
|
||||
}
|
||||
|
||||
void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, bool upper,
|
||||
u32 val)
|
||||
{
|
||||
if (upper) {
|
||||
/* Upper BAT */
|
||||
u32 bl = (val >> 2) & 0x7ff;
|
||||
bat->bepi_mask = (~bl << 17);
|
||||
bat->bepi = val & 0xfffe0000;
|
||||
bat->vs = (val & 2) ? 1 : 0;
|
||||
bat->vp = (val & 1) ? 1 : 0;
|
||||
bat->raw = (bat->raw & 0xffffffff00000000ULL) | val;
|
||||
} else {
|
||||
/* Lower BAT */
|
||||
bat->brpn = val & 0xfffe0000;
|
||||
bat->wimg = (val >> 3) & 0xf;
|
||||
bat->pp = val & 3;
|
||||
bat->raw = (bat->raw & 0x00000000ffffffffULL) | ((u64)val << 32);
|
||||
}
|
||||
}
|
||||
|
||||
static void kvmppc_write_bat(struct kvm_vcpu *vcpu, int sprn, u32 val)
|
||||
{
|
||||
struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
|
||||
struct kvmppc_bat *bat;
|
||||
|
||||
switch (sprn) {
|
||||
case SPRN_IBAT0U ... SPRN_IBAT3L:
|
||||
bat = &vcpu_book3s->ibat[(sprn - SPRN_IBAT0U) / 2];
|
||||
break;
|
||||
case SPRN_IBAT4U ... SPRN_IBAT7L:
|
||||
bat = &vcpu_book3s->ibat[(sprn - SPRN_IBAT4U) / 2];
|
||||
break;
|
||||
case SPRN_DBAT0U ... SPRN_DBAT3L:
|
||||
bat = &vcpu_book3s->dbat[(sprn - SPRN_DBAT0U) / 2];
|
||||
break;
|
||||
case SPRN_DBAT4U ... SPRN_DBAT7L:
|
||||
bat = &vcpu_book3s->dbat[(sprn - SPRN_DBAT4U) / 2];
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
kvmppc_set_bat(vcpu, bat, !(sprn % 2), val);
|
||||
}
|
||||
|
||||
int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
|
||||
{
|
||||
int emulated = EMULATE_DONE;
|
||||
|
||||
switch (sprn) {
|
||||
case SPRN_SDR1:
|
||||
to_book3s(vcpu)->sdr1 = vcpu->arch.gpr[rs];
|
||||
break;
|
||||
case SPRN_DSISR:
|
||||
to_book3s(vcpu)->dsisr = vcpu->arch.gpr[rs];
|
||||
break;
|
||||
case SPRN_DAR:
|
||||
vcpu->arch.dear = vcpu->arch.gpr[rs];
|
||||
break;
|
||||
case SPRN_HIOR:
|
||||
to_book3s(vcpu)->hior = vcpu->arch.gpr[rs];
|
||||
break;
|
||||
case SPRN_IBAT0U ... SPRN_IBAT3L:
|
||||
case SPRN_IBAT4U ... SPRN_IBAT7L:
|
||||
case SPRN_DBAT0U ... SPRN_DBAT3L:
|
||||
case SPRN_DBAT4U ... SPRN_DBAT7L:
|
||||
kvmppc_write_bat(vcpu, sprn, (u32)vcpu->arch.gpr[rs]);
|
||||
/* BAT writes happen so rarely that we're ok to flush
|
||||
* everything here */
|
||||
kvmppc_mmu_pte_flush(vcpu, 0, 0);
|
||||
break;
|
||||
case SPRN_HID0:
|
||||
to_book3s(vcpu)->hid[0] = vcpu->arch.gpr[rs];
|
||||
break;
|
||||
case SPRN_HID1:
|
||||
to_book3s(vcpu)->hid[1] = vcpu->arch.gpr[rs];
|
||||
break;
|
||||
case SPRN_HID2:
|
||||
to_book3s(vcpu)->hid[2] = vcpu->arch.gpr[rs];
|
||||
break;
|
||||
case SPRN_HID4:
|
||||
to_book3s(vcpu)->hid[4] = vcpu->arch.gpr[rs];
|
||||
break;
|
||||
case SPRN_HID5:
|
||||
to_book3s(vcpu)->hid[5] = vcpu->arch.gpr[rs];
|
||||
/* guest HID5 set can change is_dcbz32 */
|
||||
if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
|
||||
(mfmsr() & MSR_HV))
|
||||
vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
|
||||
break;
|
||||
case SPRN_ICTC:
|
||||
case SPRN_THRM1:
|
||||
case SPRN_THRM2:
|
||||
case SPRN_THRM3:
|
||||
case SPRN_CTRLF:
|
||||
case SPRN_CTRLT:
|
||||
break;
|
||||
default:
|
||||
printk(KERN_INFO "KVM: invalid SPR write: %d\n", sprn);
|
||||
#ifndef DEBUG_SPR
|
||||
emulated = EMULATE_FAIL;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
return emulated;
|
||||
}
|
||||
|
||||
int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
|
||||
{
|
||||
int emulated = EMULATE_DONE;
|
||||
|
||||
switch (sprn) {
|
||||
case SPRN_SDR1:
|
||||
vcpu->arch.gpr[rt] = to_book3s(vcpu)->sdr1;
|
||||
break;
|
||||
case SPRN_DSISR:
|
||||
vcpu->arch.gpr[rt] = to_book3s(vcpu)->dsisr;
|
||||
break;
|
||||
case SPRN_DAR:
|
||||
vcpu->arch.gpr[rt] = vcpu->arch.dear;
|
||||
break;
|
||||
case SPRN_HIOR:
|
||||
vcpu->arch.gpr[rt] = to_book3s(vcpu)->hior;
|
||||
break;
|
||||
case SPRN_HID0:
|
||||
vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[0];
|
||||
break;
|
||||
case SPRN_HID1:
|
||||
vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[1];
|
||||
break;
|
||||
case SPRN_HID2:
|
||||
vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[2];
|
||||
break;
|
||||
case SPRN_HID4:
|
||||
vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[4];
|
||||
break;
|
||||
case SPRN_HID5:
|
||||
vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[5];
|
||||
break;
|
||||
case SPRN_THRM1:
|
||||
case SPRN_THRM2:
|
||||
case SPRN_THRM3:
|
||||
case SPRN_CTRLF:
|
||||
case SPRN_CTRLT:
|
||||
vcpu->arch.gpr[rt] = 0;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_INFO "KVM: invalid SPR read: %d\n", sprn);
|
||||
#ifndef DEBUG_SPR
|
||||
emulated = EMULATE_FAIL;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
return emulated;
|
||||
}
|
||||
|
24
arch/powerpc/kvm/book3s_64_exports.c
Normal file
24
arch/powerpc/kvm/book3s_64_exports.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright SUSE Linux Products GmbH 2009
|
||||
*
|
||||
* Authors: Alexander Graf <agraf@suse.de>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <asm/kvm_book3s.h>
|
||||
|
||||
EXPORT_SYMBOL_GPL(kvmppc_trampoline_enter);
|
||||
EXPORT_SYMBOL_GPL(kvmppc_trampoline_lowmem);
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue