mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 08:10:54 +07:00
powerpc updates for 4.10
Highlights include: - Support for the kexec_file_load() syscall, which is a prereq for secure and trusted boot. - Prevent kernel execution of userspace on P9 Radix (similar to SMEP/PXN). - Sort the exception tables at build time, to save time at boot, and store them as relative offsets to save space in the kernel image & memory. - Allow building the kernel with thin archives, which should allow us to build an allyesconfig once some other fixes land. - Build fixes to allow us to correctly rebuild when changing the kernel endian from big to little or vice versa. - Plumbing so that we can avoid doing a full mm TLB flush on P9 Radix. - Initial stack protector support (-fstack-protector). - Support for dumping the radix (aka. Linux) and hash page tables via debugfs. - Fix an oops in cxl coredump generation when cxl_get_fd() is used. - Freescale updates from Scott: "Highlights include 8xx hugepage support, qbman fixes/cleanup, device tree updates, and some misc cleanup." - Many and varied fixes and minor enhancements as always. Thanks to: Alexey Kardashevskiy, Andrew Donnellan, Aneesh Kumar K.V, Anshuman Khandual, Anton Blanchard, Balbir Singh, Bartlomiej Zolnierkiewicz, Christophe Jaillet, Christophe Leroy, Denis Kirjanov, Elimar Riesebieter, Frederic Barrat, Gautham R. Shenoy, Geliang Tang, Geoff Levand, Jack Miller, Johan Hovold, Lars-Peter Clausen, Libin, Madhavan Srinivasan, Michael Neuling, Nathan Fontenot, Naveen N. Rao, Nicholas Piggin, Pan Xinhui, Peter Senna Tschudin, Rashmica Gupta, Rui Teng, Russell Currey, Scott Wood, Simon Guo, Suraj Jitindar Singh, Thiago Jung Bauermann, Tobias Klauser, Vaibhav Jain. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJYU4YSAAoJEFHr6jzI4aWAC4gQALtIAqqPon0Cd5b/FVVcMbW7 mMqB2b/0FGEl5GoRTzGUDaQqElilm6AEVfHO86C7DFji/a6olneFfw87iz+mtWuZ JvrNq68ZiSnoeszdUy4MgtXFLb5sTzNMev4skaHfjI9E5CepWBoR0zH4G+kNVnd5 WSgudv8Cq4Px+MEuTOigt3QYjHzZ3cw/XNOOm9c+oGj+PDW4O9UItVI+S1WLoey4 rAB2nRcLMDPuwfRQC9XsF3zEbkv4h1dEXo/EBRuRpcF+0lLTzFw1lv1WE8OxlUmS kAXbty3dIytBfSbtJT0c0Ps6sfQ4HFhu6ZV2fjnxNTz2KDkBIN7LBYHmBYiqY9oZ 9zvbUWtfiTu5ocfRtTq7rC/Hcj4Kbr9S9F/FvXR0WyDsKgu4xxAovqC3gcn6YjYK Rr1tcCI4nUzyhVJVmd+OEhUvc5JbFy9aGage+YeOyejfvvSbXIunaxWlPjoDkvim Vjl+UKU8gw51XFssqY5ZBi/HNlMFKYedLpMFp/fItnLglhj50V0eFWkpDgdSCYom vo9ifPLZx8n8m8De3H7TV4E0F4gCHcTeqZdu7tW9AAUVM6iLJcDLm3asGmtNh21t snOHNOJ5QSIno6ezUUg29T6VBjbPh46fdJJSlIZrEe8OzLZ1haGyttf0tD00PQvY Z2W/m3gxafnOeGgBqvyv =xOzf -----END PGP SIGNATURE----- Merge tag 'powerpc-4.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux Pull powerpc updates from Michael Ellerman: "Highlights include: - Support for the kexec_file_load() syscall, which is a prereq for secure and trusted boot. - Prevent kernel execution of userspace on P9 Radix (similar to SMEP/PXN). - Sort the exception tables at build time, to save time at boot, and store them as relative offsets to save space in the kernel image & memory. - Allow building the kernel with thin archives, which should allow us to build an allyesconfig once some other fixes land. - Build fixes to allow us to correctly rebuild when changing the kernel endian from big to little or vice versa. - Plumbing so that we can avoid doing a full mm TLB flush on P9 Radix. - Initial stack protector support (-fstack-protector). - Support for dumping the radix (aka. Linux) and hash page tables via debugfs. - Fix an oops in cxl coredump generation when cxl_get_fd() is used. - Freescale updates from Scott: "Highlights include 8xx hugepage support, qbman fixes/cleanup, device tree updates, and some misc cleanup." - Many and varied fixes and minor enhancements as always. Thanks to: Alexey Kardashevskiy, Andrew Donnellan, Aneesh Kumar K.V, Anshuman Khandual, Anton Blanchard, Balbir Singh, Bartlomiej Zolnierkiewicz, Christophe Jaillet, Christophe Leroy, Denis Kirjanov, Elimar Riesebieter, Frederic Barrat, Gautham R. Shenoy, Geliang Tang, Geoff Levand, Jack Miller, Johan Hovold, Lars-Peter Clausen, Libin, Madhavan Srinivasan, Michael Neuling, Nathan Fontenot, Naveen N. Rao, Nicholas Piggin, Pan Xinhui, Peter Senna Tschudin, Rashmica Gupta, Rui Teng, Russell Currey, Scott Wood, Simon Guo, Suraj Jitindar Singh, Thiago Jung Bauermann, Tobias Klauser, Vaibhav Jain" [ And thanks to Michael, who took time off from a new baby to get this pull request done. - Linus ] * tag 'powerpc-4.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (174 commits) powerpc/fsl/dts: add FMan node for t1042d4rdb powerpc/fsl/dts: add sg_2500_aqr105_phy4 alias on t1024rdb powerpc/fsl/dts: add QMan and BMan nodes on t1024 powerpc/fsl/dts: add QMan and BMan nodes on t1023 soc/fsl/qman: test: use DEFINE_SPINLOCK() powerpc/fsl-lbc: use DEFINE_SPINLOCK() powerpc/8xx: Implement support of hugepages powerpc: get hugetlbpage handling more generic powerpc: port 64 bits pgtable_cache to 32 bits powerpc/boot: Request no dynamic linker for boot wrapper soc/fsl/bman: Use resource_size instead of computation soc/fsl/qe: use builtin_platform_driver powerpc/fsl_pmc: use builtin_platform_driver powerpc/83xx/suspend: use builtin_platform_driver powerpc/ftrace: Fix the comments for ftrace_modify_code powerpc/perf: macros for power9 format encoding powerpc/perf: power9 raw event format encoding powerpc/perf: update attribute_group data structure powerpc/perf: factor out the event format field powerpc/mm/iommu, vfio/spapr: Put pages on VFIO container shutdown ...
This commit is contained in:
commit
de399813b5
@ -169,4 +169,5 @@ ti,tsc2003 I2C Touch-Screen Controller
|
||||
ti,tmp102 Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface
|
||||
ti,tmp103 Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface
|
||||
ti,tmp275 Digital Temperature Sensor
|
||||
winbond,w83793 Winbond/Nuvoton H/W Monitor
|
||||
winbond,wpct301 i2c trusted platform module (TPM)
|
||||
|
@ -80,6 +80,7 @@ config ARCH_HAS_DMA_SET_COHERENT_MASK
|
||||
config PPC
|
||||
bool
|
||||
default y
|
||||
select BUILDTIME_EXTABLE_SORT
|
||||
select ARCH_MIGHT_HAVE_PC_PARPORT
|
||||
select ARCH_MIGHT_HAVE_PC_SERIO
|
||||
select BINFMT_ELF
|
||||
@ -163,6 +164,7 @@ config PPC
|
||||
select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE
|
||||
select HAVE_ARCH_HARDENED_USERCOPY
|
||||
select HAVE_KERNEL_GZIP
|
||||
select HAVE_CC_STACKPROTECTOR
|
||||
|
||||
config GENERIC_CSUM
|
||||
def_bool CPU_LITTLE_ENDIAN
|
||||
@ -396,6 +398,14 @@ config MPROFILE_KERNEL
|
||||
depends on PPC64 && CPU_LITTLE_ENDIAN
|
||||
def_bool !DISABLE_MPROFILE_KERNEL
|
||||
|
||||
config USE_THIN_ARCHIVES
|
||||
bool "Build the kernel using thin archives"
|
||||
default n
|
||||
select THIN_ARCHIVES
|
||||
help
|
||||
Build the kernel using thin archives.
|
||||
If you're unsure say N.
|
||||
|
||||
config IOMMU_HELPER
|
||||
def_bool PPC64
|
||||
|
||||
@ -456,6 +466,19 @@ config KEXEC
|
||||
interface is strongly in flux, so no good recommendation can be
|
||||
made.
|
||||
|
||||
config KEXEC_FILE
|
||||
bool "kexec file based system call"
|
||||
select KEXEC_CORE
|
||||
select BUILD_BIN2C
|
||||
depends on PPC64
|
||||
depends on CRYPTO=y
|
||||
depends on CRYPTO_SHA256=y
|
||||
help
|
||||
This is a new version of the kexec system call. This call is
|
||||
file based and takes in file descriptors as system call arguments
|
||||
for kernel and initramfs as opposed to a list of segments as is the
|
||||
case for the older kexec call.
|
||||
|
||||
config RELOCATABLE
|
||||
bool "Build a relocatable kernel"
|
||||
depends on (PPC64 && !COMPILE_TEST) || (FLATMEM && (44x || FSL_BOOKE))
|
||||
@ -479,6 +502,15 @@ config RELOCATABLE
|
||||
setting can still be useful to bootwrappers that need to know the
|
||||
load address of the kernel (eg. u-boot/mkimage).
|
||||
|
||||
config RELOCATABLE_TEST
|
||||
bool "Test relocatable kernel"
|
||||
depends on (PPC64 && RELOCATABLE)
|
||||
default n
|
||||
help
|
||||
This runs the relocatable kernel at the address it was initially
|
||||
loaded at, which tends to be non-zero and therefore test the
|
||||
relocation code.
|
||||
|
||||
config CRASH_DUMP
|
||||
bool "Build a kdump crash kernel"
|
||||
depends on PPC64 || 6xx || FSL_BOOKE || (44x && !SMP)
|
||||
@ -490,7 +522,7 @@ config CRASH_DUMP
|
||||
|
||||
config FA_DUMP
|
||||
bool "Firmware-assisted dump"
|
||||
depends on PPC64 && PPC_RTAS && CRASH_DUMP && KEXEC
|
||||
depends on PPC64 && PPC_RTAS && CRASH_DUMP && KEXEC_CORE
|
||||
help
|
||||
A robust mechanism to get reliable kernel crash dump with
|
||||
assistance from firmware. This approach does not use kexec,
|
||||
@ -549,6 +581,13 @@ config ARCH_SPARSEMEM_DEFAULT
|
||||
config SYS_SUPPORTS_HUGETLBFS
|
||||
bool
|
||||
|
||||
config ILLEGAL_POINTER_VALUE
|
||||
hex
|
||||
# This is roughly half way between the top of user space and the bottom
|
||||
# of kernel space, which seems about as good as we can get.
|
||||
default 0x5deadbeef0000000 if PPC64
|
||||
default 0
|
||||
|
||||
source "mm/Kconfig"
|
||||
|
||||
config ARCH_MEMORY_PROBE
|
||||
|
@ -354,4 +354,20 @@ config FAIL_IOMMU
|
||||
|
||||
If you are unsure, say N.
|
||||
|
||||
config PPC_PTDUMP
|
||||
bool "Export kernel pagetable layout to userspace via debugfs"
|
||||
depends on DEBUG_KERNEL
|
||||
select DEBUG_FS
|
||||
help
|
||||
This option exports the state of the kernel pagetables to a
|
||||
debugfs file. This is only useful for kernel developers who are
|
||||
working in architecture specific areas of the kernel - probably
|
||||
not a good idea to enable this feature in a production kernel.
|
||||
|
||||
If you are unsure, say N.
|
||||
|
||||
config PPC_HTDUMP
|
||||
def_bool y
|
||||
depends on PPC_PTDUMP && PPC_BOOK3S
|
||||
|
||||
endmenu
|
||||
|
@ -23,7 +23,7 @@ CROSS32AR := $(CROSS32_COMPILE)ar
|
||||
ifeq ($(HAS_BIARCH),y)
|
||||
ifeq ($(CROSS32_COMPILE),)
|
||||
CROSS32CC := $(CC) -m32
|
||||
CROSS32AR := GNUTARGET=elf32-powerpc $(AR)
|
||||
KBUILD_ARFLAGS += --target=elf32-powerpc
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -85,7 +85,7 @@ ifeq ($(HAS_BIARCH),y)
|
||||
override AS += -a$(BITS)
|
||||
override LD += -m elf$(BITS)$(LDEMULATION)
|
||||
override CC += -m$(BITS)
|
||||
override AR := GNUTARGET=elf$(BITS)-$(GNUTARGET) $(AR)
|
||||
KBUILD_ARFLAGS += --target=elf$(BITS)-$(GNUTARGET)
|
||||
endif
|
||||
|
||||
LDFLAGS_vmlinux-y := -Bstatic
|
||||
@ -121,6 +121,7 @@ CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 $(MULTIPLEWORD)
|
||||
|
||||
ifeq ($(CONFIG_PPC_BOOK3S_64),y)
|
||||
CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,-mtune=power4)
|
||||
CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=power4
|
||||
else
|
||||
CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=powerpc64
|
||||
endif
|
||||
@ -249,6 +250,7 @@ core-y += arch/powerpc/kernel/ \
|
||||
core-$(CONFIG_XMON) += arch/powerpc/xmon/
|
||||
core-$(CONFIG_KVM) += arch/powerpc/kvm/
|
||||
core-$(CONFIG_PERF_EVENTS) += arch/powerpc/perf/
|
||||
core-$(CONFIG_KEXEC_FILE) += arch/powerpc/purgatory/
|
||||
|
||||
drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
|
||||
|
||||
@ -275,16 +277,16 @@ zImage: relocs_check
|
||||
endif
|
||||
|
||||
$(BOOT_TARGETS1): vmlinux
|
||||
$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
|
||||
$(Q)$(MAKE) $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
|
||||
$(BOOT_TARGETS2): vmlinux
|
||||
$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
|
||||
$(Q)$(MAKE) $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
|
||||
|
||||
|
||||
bootwrapper_install:
|
||||
$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
|
||||
$(Q)$(MAKE) $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
|
||||
|
||||
%.dtb: scripts
|
||||
$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
|
||||
$(Q)$(MAKE) $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
|
||||
|
||||
# Used to create 'merged defconfigs'
|
||||
# To use it $(call) it with the first argument as the base defconfig
|
||||
|
@ -172,10 +172,6 @@ $(addprefix $(obj)/,$(libfdt) $(libfdtheader)): $(obj)/%: $(srctree)/scripts/dtc
|
||||
$(obj)/empty.c:
|
||||
$(Q)touch $@
|
||||
|
||||
$(obj)/zImage.lds: $(obj)/%: $(srctree)/$(src)/%.S
|
||||
$(CROSS32CC) $(cpp_flags) -E -Wp,-MD,$(depfile) -P -Upowerpc \
|
||||
-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
|
||||
|
||||
$(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds : $(obj)/%: $(srctree)/$(src)/%.S
|
||||
$(Q)cp $< $@
|
||||
|
||||
@ -357,17 +353,17 @@ $(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz
|
||||
# Don't put the ramdisk on the pattern rule; when its missing make will try
|
||||
# the pattern rule with less dependencies that also matches (even with the
|
||||
# hard dependency listed).
|
||||
$(obj)/zImage.initrd.%: vmlinux $(wrapperbits)
|
||||
$(obj)/zImage.initrd.%: vmlinux $(wrapperbits) FORCE
|
||||
$(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz)
|
||||
|
||||
$(addprefix $(obj)/, $(sort $(filter zImage.%, $(image-y)))): vmlinux $(wrapperbits)
|
||||
$(addprefix $(obj)/, $(sort $(filter zImage.%, $(image-y)))): vmlinux $(wrapperbits) FORCE
|
||||
$(call if_changed,wrap,$(subst $(obj)/zImage.,,$@))
|
||||
|
||||
# dtbImage% - a dtbImage is a zImage with an embedded device tree blob
|
||||
$(obj)/dtbImage.initrd.%: vmlinux $(wrapperbits) $(obj)/%.dtb
|
||||
$(obj)/dtbImage.initrd.%: vmlinux $(wrapperbits) $(obj)/%.dtb FORCE
|
||||
$(call if_changed,wrap,$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
|
||||
|
||||
$(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb
|
||||
$(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb FORCE
|
||||
$(call if_changed,wrap,$*,,$(obj)/$*.dtb)
|
||||
|
||||
# This cannot be in the root of $(src) as the zImage rule always adds a $(obj)
|
||||
@ -375,31 +371,31 @@ $(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb
|
||||
$(obj)/vmlinux.strip: vmlinux
|
||||
$(STRIP) -s -R .comment $< -o $@
|
||||
|
||||
$(obj)/uImage: vmlinux $(wrapperbits)
|
||||
$(obj)/uImage: vmlinux $(wrapperbits) FORCE
|
||||
$(call if_changed,wrap,uboot)
|
||||
|
||||
$(obj)/uImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
|
||||
$(obj)/uImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
|
||||
$(call if_changed,wrap,uboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
|
||||
|
||||
$(obj)/uImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
|
||||
$(obj)/uImage.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
|
||||
$(call if_changed,wrap,uboot-$*,,$(obj)/$*.dtb)
|
||||
|
||||
$(obj)/cuImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
|
||||
$(obj)/cuImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
|
||||
$(call if_changed,wrap,cuboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
|
||||
|
||||
$(obj)/cuImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
|
||||
$(obj)/cuImage.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
|
||||
$(call if_changed,wrap,cuboot-$*,,$(obj)/$*.dtb)
|
||||
|
||||
$(obj)/simpleImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
|
||||
$(obj)/simpleImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
|
||||
$(call if_changed,wrap,simpleboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
|
||||
|
||||
$(obj)/simpleImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
|
||||
$(obj)/simpleImage.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
|
||||
$(call if_changed,wrap,simpleboot-$*,,$(obj)/$*.dtb)
|
||||
|
||||
$(obj)/treeImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
|
||||
$(obj)/treeImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
|
||||
$(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
|
||||
|
||||
$(obj)/treeImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
|
||||
$(obj)/treeImage.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
|
||||
$(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb)
|
||||
|
||||
# Rule to build device tree blobs
|
||||
|
@ -41,6 +41,27 @@ / {
|
||||
#size-cells = <2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
bman_fbpr: bman-fbpr {
|
||||
size = <0 0x1000000>;
|
||||
alignment = <0 0x1000000>;
|
||||
};
|
||||
|
||||
qman_fqd: qman-fqd {
|
||||
size = <0 0x400000>;
|
||||
alignment = <0 0x400000>;
|
||||
};
|
||||
|
||||
qman_pfdr: qman-pfdr {
|
||||
size = <0 0x2000000>;
|
||||
alignment = <0 0x2000000>;
|
||||
};
|
||||
};
|
||||
|
||||
ifc: localbus@ffe124000 {
|
||||
reg = <0xf 0xfe124000 0 0x2000>;
|
||||
ranges = <0 0 0xf 0xe8000000 0x08000000
|
||||
@ -72,6 +93,14 @@ dcsr: dcsr@f00000000 {
|
||||
ranges = <0x00000000 0xf 0x00000000 0x01072000>;
|
||||
};
|
||||
|
||||
bportals: bman-portals@ff4000000 {
|
||||
ranges = <0x0 0xf 0xf4000000 0x2000000>;
|
||||
};
|
||||
|
||||
qportals: qman-portals@ff6000000 {
|
||||
ranges = <0x0 0xf 0xf6000000 0x2000000>;
|
||||
};
|
||||
|
||||
soc: soc@ffe000000 {
|
||||
ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
|
||||
reg = <0xf 0xfe000000 0 0x00001000>;
|
||||
|
@ -34,6 +34,21 @@
|
||||
|
||||
#include <dt-bindings/thermal/thermal.h>
|
||||
|
||||
&bman_fbpr {
|
||||
compatible = "fsl,bman-fbpr";
|
||||
alloc-ranges = <0 0 0x10000 0>;
|
||||
};
|
||||
|
||||
&qman_fqd {
|
||||
compatible = "fsl,qman-fqd";
|
||||
alloc-ranges = <0 0 0x10000 0>;
|
||||
};
|
||||
|
||||
&qman_pfdr {
|
||||
compatible = "fsl,qman-pfdr";
|
||||
alloc-ranges = <0 0 0x10000 0>;
|
||||
};
|
||||
|
||||
&ifc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
@ -180,6 +195,92 @@ dcsr-cpu-sb-proxy@108000 {
|
||||
};
|
||||
};
|
||||
|
||||
&bportals {
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x1>;
|
||||
compatible = "simple-bus";
|
||||
|
||||
bman-portal@0 {
|
||||
cell-index = <0x0>;
|
||||
compatible = "fsl,bman-portal";
|
||||
reg = <0x0 0x4000>, <0x1000000 0x1000>;
|
||||
interrupts = <105 2 0 0>;
|
||||
};
|
||||
bman-portal@4000 {
|
||||
cell-index = <0x1>;
|
||||
compatible = "fsl,bman-portal";
|
||||
reg = <0x4000 0x4000>, <0x1001000 0x1000>;
|
||||
interrupts = <107 2 0 0>;
|
||||
};
|
||||
bman-portal@8000 {
|
||||
cell-index = <2>;
|
||||
compatible = "fsl,bman-portal";
|
||||
reg = <0x8000 0x4000>, <0x1002000 0x1000>;
|
||||
interrupts = <109 2 0 0>;
|
||||
};
|
||||
bman-portal@c000 {
|
||||
cell-index = <0x3>;
|
||||
compatible = "fsl,bman-portal";
|
||||
reg = <0xc000 0x4000>, <0x1003000 0x1000>;
|
||||
interrupts = <111 2 0 0>;
|
||||
};
|
||||
bman-portal@10000 {
|
||||
cell-index = <0x4>;
|
||||
compatible = "fsl,bman-portal";
|
||||
reg = <0x10000 0x4000>, <0x1004000 0x1000>;
|
||||
interrupts = <113 2 0 0>;
|
||||
};
|
||||
bman-portal@14000 {
|
||||
cell-index = <0x5>;
|
||||
compatible = "fsl,bman-portal";
|
||||
reg = <0x14000 0x4000>, <0x1005000 0x1000>;
|
||||
interrupts = <115 2 0 0>;
|
||||
};
|
||||
};
|
||||
|
||||
&qportals {
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x1>;
|
||||
compatible = "simple-bus";
|
||||
|
||||
qportal0: qman-portal@0 {
|
||||
compatible = "fsl,qman-portal";
|
||||
reg = <0x0 0x4000>, <0x1000000 0x1000>;
|
||||
interrupts = <104 0x2 0 0>;
|
||||
cell-index = <0x0>;
|
||||
};
|
||||
qportal1: qman-portal@4000 {
|
||||
compatible = "fsl,qman-portal";
|
||||
reg = <0x4000 0x4000>, <0x1001000 0x1000>;
|
||||
interrupts = <106 0x2 0 0>;
|
||||
cell-index = <0x1>;
|
||||
};
|
||||
qportal2: qman-portal@8000 {
|
||||
compatible = "fsl,qman-portal";
|
||||
reg = <0x8000 0x4000>, <0x1002000 0x1000>;
|
||||
interrupts = <108 0x2 0 0>;
|
||||
cell-index = <0x2>;
|
||||
};
|
||||
qportal3: qman-portal@c000 {
|
||||
compatible = "fsl,qman-portal";
|
||||
reg = <0xc000 0x4000>, <0x1003000 0x1000>;
|
||||
interrupts = <110 0x2 0 0>;
|
||||
cell-index = <0x3>;
|
||||
};
|
||||
qportal4: qman-portal@10000 {
|
||||
compatible = "fsl,qman-portal";
|
||||
reg = <0x10000 0x4000>, <0x1004000 0x1000>;
|
||||
interrupts = <112 0x2 0 0>;
|
||||
cell-index = <0x4>;
|
||||
};
|
||||
qportal5: qman-portal@14000 {
|
||||
compatible = "fsl,qman-portal";
|
||||
reg = <0x14000 0x4000>, <0x1005000 0x1000>;
|
||||
interrupts = <114 0x2 0 0>;
|
||||
cell-index = <0x5>;
|
||||
};
|
||||
};
|
||||
|
||||
&soc {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
@ -413,6 +514,8 @@ sata@220000 {
|
||||
};
|
||||
|
||||
/include/ "qoriq-sec5.0-0.dtsi"
|
||||
/include/ "qoriq-qman3.dtsi"
|
||||
/include/ "qoriq-bman1.dtsi"
|
||||
|
||||
/include/ "qoriq-fman3l-0.dtsi"
|
||||
/include/ "qoriq-fman3-0-10g-0-best-effort.dtsi"
|
||||
|
@ -41,6 +41,27 @@ / {
|
||||
#size-cells = <2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
bman_fbpr: bman-fbpr {
|
||||
size = <0 0x1000000>;
|
||||
alignment = <0 0x1000000>;
|
||||
};
|
||||
|
||||
qman_fqd: qman-fqd {
|
||||
size = <0 0x400000>;
|
||||
alignment = <0 0x400000>;
|
||||
};
|
||||
|
||||
qman_pfdr: qman-pfdr {
|
||||
size = <0 0x2000000>;
|
||||
alignment = <0 0x2000000>;
|
||||
};
|
||||
};
|
||||
|
||||
ifc: localbus@ffe124000 {
|
||||
reg = <0xf 0xfe124000 0 0x2000>;
|
||||
ranges = <0 0 0xf 0xe8000000 0x08000000
|
||||
@ -80,6 +101,14 @@ dcsr: dcsr@f00000000 {
|
||||
ranges = <0x00000000 0xf 0x00000000 0x01072000>;
|
||||
};
|
||||
|
||||
bportals: bman-portals@ff4000000 {
|
||||
ranges = <0x0 0xf 0xf4000000 0x2000000>;
|
||||
};
|
||||
|
||||
qportals: qman-portals@ff6000000 {
|
||||
ranges = <0x0 0xf 0xf6000000 0x2000000>;
|
||||
};
|
||||
|
||||
soc: soc@ffe000000 {
|
||||
ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
|
||||
reg = <0xf 0xfe000000 0 0x00001000>;
|
||||
|
@ -41,6 +41,31 @@ / {
|
||||
#size-cells = <2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
|
||||
aliases {
|
||||
sg_2500_aqr105_phy4 = &sg_2500_aqr105_phy4;
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
bman_fbpr: bman-fbpr {
|
||||
size = <0 0x1000000>;
|
||||
alignment = <0 0x1000000>;
|
||||
};
|
||||
|
||||
qman_fqd: qman-fqd {
|
||||
size = <0 0x400000>;
|
||||
alignment = <0 0x400000>;
|
||||
};
|
||||
|
||||
qman_pfdr: qman-pfdr {
|
||||
size = <0 0x2000000>;
|
||||
alignment = <0 0x2000000>;
|
||||
};
|
||||
};
|
||||
|
||||
ifc: localbus@ffe124000 {
|
||||
reg = <0xf 0xfe124000 0 0x2000>;
|
||||
ranges = <0 0 0xf 0xe8000000 0x08000000
|
||||
@ -82,6 +107,14 @@ dcsr: dcsr@f00000000 {
|
||||
ranges = <0x00000000 0xf 0x00000000 0x01072000>;
|
||||
};
|
||||
|
||||
bportals: bman-portals@ff4000000 {
|
||||
ranges = <0x0 0xf 0xf4000000 0x2000000>;
|
||||
};
|
||||
|
||||
qportals: qman-portals@ff6000000 {
|
||||
ranges = <0x0 0xf 0xf6000000 0x2000000>;
|
||||
};
|
||||
|
||||
soc: soc@ffe000000 {
|
||||
ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
|
||||
reg = <0xf 0xfe000000 0 0x00001000>;
|
||||
|
@ -48,6 +48,58 @@ cpld@3,0 {
|
||||
"fsl,deepsleep-cpld";
|
||||
};
|
||||
};
|
||||
|
||||
soc: soc@ffe000000 {
|
||||
fman0: fman@400000 {
|
||||
ethernet@e0000 {
|
||||
phy-handle = <&phy_sgmii_0>;
|
||||
phy-connection-type = "sgmii";
|
||||
};
|
||||
|
||||
ethernet@e2000 {
|
||||
phy-handle = <&phy_sgmii_1>;
|
||||
phy-connection-type = "sgmii";
|
||||
};
|
||||
|
||||
ethernet@e4000 {
|
||||
phy-handle = <&phy_sgmii_2>;
|
||||
phy-connection-type = "sgmii";
|
||||
};
|
||||
|
||||
ethernet@e6000 {
|
||||
phy-handle = <&phy_rgmii_0>;
|
||||
phy-connection-type = "rgmii";
|
||||
};
|
||||
|
||||
ethernet@e8000 {
|
||||
phy-handle = <&phy_rgmii_1>;
|
||||
phy-connection-type = "rgmii";
|
||||
};
|
||||
|
||||
mdio0: mdio@fc000 {
|
||||
phy_sgmii_0: ethernet-phy@02 {
|
||||
reg = <0x02>;
|
||||
};
|
||||
|
||||
phy_sgmii_1: ethernet-phy@03 {
|
||||
reg = <0x03>;
|
||||
};
|
||||
|
||||
phy_sgmii_2: ethernet-phy@01 {
|
||||
reg = <0x01>;
|
||||
};
|
||||
|
||||
phy_rgmii_0: ethernet-phy@04 {
|
||||
reg = <0x04>;
|
||||
};
|
||||
|
||||
phy_rgmii_1: ethernet-phy@05 {
|
||||
reg = <0x05>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#include "t1042si-post.dtsi"
|
||||
|
@ -125,6 +125,10 @@ flash@0 {
|
||||
};
|
||||
|
||||
i2c@118000 {
|
||||
hwmon@2f {
|
||||
compatible = "winbond,w83793";
|
||||
reg = <0x2f>;
|
||||
};
|
||||
eeprom@52 {
|
||||
compatible = "at24,24c256";
|
||||
reg = <0x52>;
|
||||
|
@ -57,11 +57,6 @@ __system_reset_overlay:
|
||||
bctr
|
||||
|
||||
1:
|
||||
/* Save the value at addr zero for a null pointer write check later. */
|
||||
|
||||
li r4, 0
|
||||
lwz r3, 0(r4)
|
||||
|
||||
/* Primary delays then goes to _zimage_start in wrapper. */
|
||||
|
||||
or 31, 31, 31 /* db16cyc */
|
||||
|
@ -119,13 +119,12 @@ void ps3_copy_vectors(void)
|
||||
flush_cache((void *)0x100, 512);
|
||||
}
|
||||
|
||||
void platform_init(unsigned long null_check)
|
||||
void platform_init(void)
|
||||
{
|
||||
const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */
|
||||
void *chosen;
|
||||
unsigned long ft_addr;
|
||||
u64 rm_size;
|
||||
unsigned long val;
|
||||
|
||||
console_ops.write = ps3_console_write;
|
||||
platform_ops.exit = ps3_exit;
|
||||
@ -153,11 +152,6 @@ void platform_init(unsigned long null_check)
|
||||
|
||||
printf(" flat tree at 0x%lx\n\r", ft_addr);
|
||||
|
||||
val = *(unsigned long *)0;
|
||||
|
||||
if (val != null_check)
|
||||
printf("null check failed: %lx != %lx\n\r", val, null_check);
|
||||
|
||||
((kernel_entry_t)0)(ft_addr, 0, NULL);
|
||||
|
||||
ps3_exit();
|
||||
|
@ -181,6 +181,28 @@ case "$elfformat" in
|
||||
elf32-powerpc) format=elf32ppc ;;
|
||||
esac
|
||||
|
||||
ld_version()
|
||||
{
|
||||
# Poached from scripts/ld-version.sh, but we don't want to call that because
|
||||
# this script (wrapper) is distributed separately from the kernel source.
|
||||
# Extract linker version number from stdin and turn into single number.
|
||||
awk '{
|
||||
gsub(".*\\)", "");
|
||||
gsub(".*version ", "");
|
||||
gsub("-.*", "");
|
||||
split($1,a, ".");
|
||||
print a[1]*100000000 + a[2]*1000000 + a[3]*10000;
|
||||
exit
|
||||
}'
|
||||
}
|
||||
|
||||
# Do not include PT_INTERP segment when linking pie. Non-pie linking
|
||||
# just ignores this option.
|
||||
LD_VERSION=$(${CROSS}ld --version | ld_version)
|
||||
LD_NO_DL_MIN_VERSION=$(echo 2.26 | ld_version)
|
||||
if [ "$LD_VERSION" -ge "$LD_NO_DL_MIN_VERSION" ] ; then
|
||||
nodl="--no-dynamic-linker"
|
||||
fi
|
||||
|
||||
platformo=$object/"$platform".o
|
||||
lds=$object/zImage.lds
|
||||
@ -446,7 +468,7 @@ if [ "$platform" != "miboot" ]; then
|
||||
text_start="-Ttext $link_address"
|
||||
fi
|
||||
#link everything
|
||||
${CROSS}ld -m $format -T $lds $text_start $pie -o "$ofile" \
|
||||
${CROSS}ld -m $format -T $lds $text_start $pie $nodl -o "$ofile" \
|
||||
$platformo $tmp $object/wrapper.a
|
||||
rm $tmp
|
||||
fi
|
||||
|
@ -45,12 +45,6 @@ CONFIG_PARPORT_PC_FIFO=y
|
||||
CONFIG_BLK_DEV_FD=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_IDE=y
|
||||
CONFIG_BLK_DEV_IDECD=y
|
||||
# CONFIG_IDEPCI_PCIBUS_ORDER is not set
|
||||
CONFIG_BLK_DEV_GENERIC=y
|
||||
CONFIG_BLK_DEV_SIIMAGE=y
|
||||
CONFIG_BLK_DEV_VIA82CXXX=y
|
||||
CONFIG_SCSI=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_CHR_DEV_ST=y
|
||||
@ -61,6 +55,10 @@ CONFIG_SCSI_CONSTANTS=y
|
||||
CONFIG_SCSI_SYM53C8XX_2=y
|
||||
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
|
||||
# CONFIG_SCSI_SYM53C8XX_MMIO is not set
|
||||
CONFIG_ATA=y
|
||||
CONFIG_PATA_SIL680=y
|
||||
CONFIG_PATA_VIA=y
|
||||
CONFIG_ATA_GENERIC=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_VORTEX=y
|
||||
CONFIG_8139CP=y
|
||||
|
@ -108,16 +108,15 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_SIZE=131072
|
||||
CONFIG_IDE=y
|
||||
CONFIG_BLK_DEV_GENERIC=y
|
||||
CONFIG_BLK_DEV_AEC62XX=y
|
||||
CONFIG_BLK_DEV_SIIMAGE=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_BLK_DEV_SR=m
|
||||
CONFIG_CHR_DEV_SG=y
|
||||
CONFIG_ATA=y
|
||||
CONFIG_SATA_PROMISE=y
|
||||
CONFIG_PATA_ARTOP=y
|
||||
CONFIG_PATA_PDC2027X=m
|
||||
CONFIG_PATA_SIL680=y
|
||||
CONFIG_ATA_GENERIC=y
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_MD=m
|
||||
CONFIG_MD_LINEAR=m
|
||||
|
@ -42,12 +42,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||
CONFIG_BLK_DEV_FD=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_IDE=y
|
||||
CONFIG_BLK_DEV_IDECD=y
|
||||
CONFIG_BLK_DEV_GENERIC=y
|
||||
CONFIG_BLK_DEV_SL82C105=y
|
||||
CONFIG_BLK_DEV_VIA82CXXX=y
|
||||
CONFIG_SCSI=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_CHR_DEV_ST=y
|
||||
CONFIG_BLK_DEV_SR=y
|
||||
@ -56,6 +50,10 @@ CONFIG_CHR_DEV_SG=y
|
||||
CONFIG_SCSI_CONSTANTS=y
|
||||
CONFIG_SCSI_SYM53C8XX_2=y
|
||||
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
|
||||
CONFIG_ATA=y
|
||||
CONFIG_PATA_VIA=y
|
||||
CONFIG_PATA_WINBOND=y
|
||||
CONFIG_ATA_GENERIC=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_PCNET32=y
|
||||
CONFIG_NET_TULIP=y
|
||||
|
@ -44,6 +44,7 @@ CONFIG_FORCE_MAX_ZONEORDER=13
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
CONFIG_FRAME_WARN=1024
|
||||
CONFIG_FTL=y
|
||||
CONFIG_GPIO_GENERIC_PLATFORM=y
|
||||
CONFIG_HFS_FS=m
|
||||
CONFIG_HFSPLUS_FS=m
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
@ -104,8 +105,13 @@ CONFIG_PACKET=y
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
CONFIG_PERF_EVENTS=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
CONFIG_POWER_SUPPLY=y
|
||||
CONFIG_POWER_RESET=y
|
||||
CONFIG_POWER_RESET_GPIO=y
|
||||
CONFIG_POWER_RESET_GPIO_RESTART=y
|
||||
CONFIG_QNX4FS_FS=m
|
||||
CONFIG_RCU_TRACE=y
|
||||
CONFIG_RESET_CONTROLLER=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_SYSV_FS=m
|
||||
CONFIG_SYSVIPC=y
|
||||
|
@ -60,10 +60,6 @@ CONFIG_BLK_DEV_NBD=m
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_SIZE=65536
|
||||
CONFIG_CDROM_PKTCDVD=m
|
||||
CONFIG_IDE=y
|
||||
CONFIG_BLK_DEV_IDECD=y
|
||||
CONFIG_BLK_DEV_IDE_PMAC=y
|
||||
CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_CHR_DEV_ST=y
|
||||
CONFIG_BLK_DEV_SR=y
|
||||
@ -73,6 +69,7 @@ CONFIG_SCSI_CONSTANTS=y
|
||||
CONFIG_SCSI_SPI_ATTRS=y
|
||||
CONFIG_ATA=y
|
||||
CONFIG_SATA_SVW=y
|
||||
CONFIG_PATA_MACIO=y
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_MD=y
|
||||
CONFIG_MD_LINEAR=y
|
||||
|
@ -39,16 +39,15 @@ CONFIG_IP_PNP_DHCP=y
|
||||
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_SIZE=8192
|
||||
CONFIG_IDE=y
|
||||
CONFIG_BLK_DEV_IDECD=y
|
||||
CONFIG_IDE_TASK_IOCTL=y
|
||||
CONFIG_BLK_DEV_GENERIC=y
|
||||
CONFIG_BLK_DEV_AMD74XX=y
|
||||
# CONFIG_SCSI_PROC_FS is not set
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_BLK_DEV_SR=y
|
||||
CONFIG_BLK_DEV_SR_VENDOR=y
|
||||
CONFIG_CHR_DEV_SG=y
|
||||
CONFIG_SCSI_IPR=y
|
||||
CONFIG_ATA=y
|
||||
CONFIG_PATA_AMD=y
|
||||
CONFIG_ATA_GENERIC=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_AMD8111_ETH=y
|
||||
CONFIG_TIGON3=y
|
||||
|
@ -58,9 +58,6 @@ CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_SIZE=16384
|
||||
CONFIG_EEPROM_LEGACY=y
|
||||
CONFIG_IDE=y
|
||||
CONFIG_BLK_DEV_IDECD=y
|
||||
CONFIG_IDE_TASK_IOCTL=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_CHR_DEV_ST=y
|
||||
CONFIG_CHR_DEV_OSST=y
|
||||
|
@ -117,15 +117,6 @@ CONFIG_CONNECTOR=y
|
||||
CONFIG_MAC_FLOPPY=m
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_IDE=y
|
||||
CONFIG_BLK_DEV_IDECS=m
|
||||
CONFIG_BLK_DEV_IDECD=y
|
||||
CONFIG_BLK_DEV_GENERIC=y
|
||||
CONFIG_BLK_DEV_PDC202XX_NEW=y
|
||||
CONFIG_BLK_DEV_SL82C105=y
|
||||
CONFIG_BLK_DEV_IDE_PMAC=y
|
||||
CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
|
||||
CONFIG_SCSI=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_CHR_DEV_ST=y
|
||||
CONFIG_BLK_DEV_SR=y
|
||||
@ -140,6 +131,12 @@ CONFIG_SCSI_SYM53C8XX_2=y
|
||||
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
|
||||
CONFIG_SCSI_MESH=y
|
||||
CONFIG_SCSI_MAC53C94=y
|
||||
CONFIG_ATA=y
|
||||
CONFIG_PATA_MACIO=y
|
||||
CONFIG_PATA_PDC2027X=y
|
||||
CONFIG_PATA_WINBOND=y
|
||||
CONFIG_PATA_PCMCIA=m
|
||||
CONFIG_ATA_GENERIC=y
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_MD=m
|
||||
CONFIG_MD_LINEAR=m
|
||||
|
@ -49,6 +49,7 @@ CONFIG_BINFMT_MISC=m
|
||||
CONFIG_PPC_TRANSACTIONAL_MEM=y
|
||||
CONFIG_HOTPLUG_CPU=y
|
||||
CONFIG_KEXEC=y
|
||||
CONFIG_KEXEC_FILE=y
|
||||
CONFIG_IRQ_ALL_CPUS=y
|
||||
CONFIG_NUMA=y
|
||||
CONFIG_MEMORY_HOTPLUG=y
|
||||
@ -241,10 +242,6 @@ CONFIG_EXT2_FS_SECURITY=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
CONFIG_EXT4_FS_SECURITY=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_REISERFS_FS_XATTR=y
|
||||
CONFIG_REISERFS_FS_POSIX_ACL=y
|
||||
CONFIG_REISERFS_FS_SECURITY=y
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_JFS_POSIX_ACL=y
|
||||
CONFIG_JFS_SECURITY=y
|
||||
@ -300,7 +297,10 @@ CONFIG_CRYPTO_TEST=m
|
||||
CONFIG_CRYPTO_CCM=m
|
||||
CONFIG_CRYPTO_PCBC=m
|
||||
CONFIG_CRYPTO_HMAC=y
|
||||
CONFIG_CRYPT_CRC32C_VPMSUM=m
|
||||
CONFIG_CRYPTO_MD5_PPC=m
|
||||
CONFIG_CRYPTO_MICHAEL_MIC=m
|
||||
CONFIG_CRYPTO_SHA256=y
|
||||
CONFIG_CRYPTO_TGR192=m
|
||||
CONFIG_CRYPTO_WP512=m
|
||||
CONFIG_CRYPTO_ANUBIS=m
|
||||
@ -308,6 +308,7 @@ CONFIG_CRYPTO_BLOWFISH=m
|
||||
CONFIG_CRYPTO_CAST6=m
|
||||
CONFIG_CRYPTO_KHAZAD=m
|
||||
CONFIG_CRYPTO_SALSA20=m
|
||||
CONFIG_CRYPTO_SHA1_PPC=m
|
||||
CONFIG_CRYPTO_SERPENT=m
|
||||
CONFIG_CRYPTO_TEA=m
|
||||
CONFIG_CRYPTO_TWOFISH=m
|
||||
|
@ -46,6 +46,7 @@ CONFIG_HZ_100=y
|
||||
CONFIG_BINFMT_MISC=m
|
||||
CONFIG_PPC_TRANSACTIONAL_MEM=y
|
||||
CONFIG_KEXEC=y
|
||||
CONFIG_KEXEC_FILE=y
|
||||
CONFIG_CRASH_DUMP=y
|
||||
CONFIG_IRQ_ALL_CPUS=y
|
||||
CONFIG_MEMORY_HOTREMOVE=y
|
||||
@ -85,12 +86,6 @@ CONFIG_BLK_DEV_NBD=m
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_SIZE=65536
|
||||
CONFIG_VIRTIO_BLK=m
|
||||
CONFIG_IDE=y
|
||||
CONFIG_BLK_DEV_IDECD=y
|
||||
CONFIG_BLK_DEV_GENERIC=y
|
||||
CONFIG_BLK_DEV_AMD74XX=y
|
||||
CONFIG_BLK_DEV_IDE_PMAC=y
|
||||
CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_CHR_DEV_ST=m
|
||||
CONFIG_BLK_DEV_SR=y
|
||||
@ -120,6 +115,9 @@ CONFIG_SATA_AHCI=y
|
||||
CONFIG_SATA_SIL24=y
|
||||
CONFIG_SATA_MV=y
|
||||
CONFIG_SATA_SVW=y
|
||||
CONFIG_PATA_AMD=y
|
||||
CONFIG_PATA_MACIO=y
|
||||
CONFIG_ATA_GENERIC=y
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_MD=y
|
||||
CONFIG_MD_LINEAR=y
|
||||
@ -335,7 +333,10 @@ CONFIG_PPC_EARLY_DEBUG=y
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
CONFIG_CRYPTO_PCBC=m
|
||||
CONFIG_CRYPTO_HMAC=y
|
||||
CONFIG_CRYPT_CRC32C_VPMSUM=m
|
||||
CONFIG_CRYPTO_MD5_PPC=m
|
||||
CONFIG_CRYPTO_MICHAEL_MIC=m
|
||||
CONFIG_CRYPTO_SHA256=y
|
||||
CONFIG_CRYPTO_TGR192=m
|
||||
CONFIG_CRYPTO_WP512=m
|
||||
CONFIG_CRYPTO_ANUBIS=m
|
||||
@ -343,6 +344,7 @@ CONFIG_CRYPTO_BLOWFISH=m
|
||||
CONFIG_CRYPTO_CAST6=m
|
||||
CONFIG_CRYPTO_KHAZAD=m
|
||||
CONFIG_CRYPTO_SALSA20=m
|
||||
CONFIG_CRYPTO_SHA1_PPC=m
|
||||
CONFIG_CRYPTO_SERPENT=m
|
||||
CONFIG_CRYPTO_TEA=m
|
||||
CONFIG_CRYPTO_TWOFISH=m
|
||||
|
@ -59,10 +59,6 @@ CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_NBD=m
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_SIZE=65536
|
||||
CONFIG_IDE=y
|
||||
CONFIG_BLK_DEV_IDECD=y
|
||||
CONFIG_BLK_DEV_GENERIC=y
|
||||
CONFIG_BLK_DEV_AMD74XX=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_CHR_DEV_ST=y
|
||||
CONFIG_BLK_DEV_SR=y
|
||||
@ -79,6 +75,8 @@ CONFIG_SCSI_DEBUG=m
|
||||
CONFIG_ATA=y
|
||||
CONFIG_SATA_SIL24=y
|
||||
CONFIG_SATA_SVW=y
|
||||
CONFIG_PATA_AMD=y
|
||||
CONFIG_ATA_GENERIC=y
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_MD=y
|
||||
CONFIG_MD_LINEAR=y
|
||||
|
@ -378,13 +378,6 @@ CONFIG_EEPROM_AT24=m
|
||||
CONFIG_EEPROM_LEGACY=m
|
||||
CONFIG_EEPROM_MAX6875=m
|
||||
CONFIG_EEPROM_93CX6=m
|
||||
CONFIG_IDE=y
|
||||
CONFIG_BLK_DEV_IDECD=m
|
||||
CONFIG_IDE_TASK_IOCTL=y
|
||||
# CONFIG_IDEPCI_PCIBUS_ORDER is not set
|
||||
CONFIG_BLK_DEV_GENERIC=y
|
||||
CONFIG_BLK_DEV_IDE_PMAC=y
|
||||
CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
|
||||
CONFIG_RAID_ATTRS=m
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_CHR_DEV_ST=m
|
||||
@ -411,13 +404,14 @@ CONFIG_ATA=y
|
||||
CONFIG_SATA_FSL=m
|
||||
CONFIG_PDC_ADMA=m
|
||||
CONFIG_ATA_PIIX=m
|
||||
CONFIG_PATA_MACIO=y
|
||||
CONFIG_PATA_MPC52xx=m
|
||||
CONFIG_PATA_OPTIDMA=m
|
||||
CONFIG_PATA_SCH=m
|
||||
CONFIG_PATA_VIA=m
|
||||
CONFIG_PATA_PLATFORM=m
|
||||
CONFIG_PATA_OF_PLATFORM=m
|
||||
CONFIG_ATA_GENERIC=m
|
||||
CONFIG_ATA_GENERIC=y
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_MD=y
|
||||
CONFIG_MD_LINEAR=m
|
||||
|
@ -52,6 +52,7 @@ CONFIG_HZ_100=y
|
||||
CONFIG_BINFMT_MISC=m
|
||||
CONFIG_PPC_TRANSACTIONAL_MEM=y
|
||||
CONFIG_KEXEC=y
|
||||
CONFIG_KEXEC_FILE=y
|
||||
CONFIG_IRQ_ALL_CPUS=y
|
||||
CONFIG_MEMORY_HOTPLUG=y
|
||||
CONFIG_MEMORY_HOTREMOVE=y
|
||||
@ -92,10 +93,6 @@ CONFIG_BLK_DEV_NBD=m
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_SIZE=65536
|
||||
CONFIG_VIRTIO_BLK=m
|
||||
CONFIG_IDE=y
|
||||
CONFIG_BLK_DEV_IDECD=y
|
||||
CONFIG_BLK_DEV_GENERIC=y
|
||||
CONFIG_BLK_DEV_AMD74XX=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_CHR_DEV_ST=m
|
||||
CONFIG_BLK_DEV_SR=y
|
||||
@ -122,7 +119,8 @@ CONFIG_SCSI_DH_RDAC=m
|
||||
CONFIG_SCSI_DH_ALUA=m
|
||||
CONFIG_ATA=y
|
||||
CONFIG_SATA_AHCI=y
|
||||
# CONFIG_ATA_SFF is not set
|
||||
CONFIG_PATA_AMD=y
|
||||
CONFIG_ATA_GENERIC=y
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_MD=y
|
||||
CONFIG_MD_LINEAR=y
|
||||
@ -244,10 +242,6 @@ CONFIG_EXT2_FS_SECURITY=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
CONFIG_EXT4_FS_SECURITY=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_REISERFS_FS_XATTR=y
|
||||
CONFIG_REISERFS_FS_POSIX_ACL=y
|
||||
CONFIG_REISERFS_FS_SECURITY=y
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_JFS_POSIX_ACL=y
|
||||
CONFIG_JFS_SECURITY=y
|
||||
@ -302,7 +296,10 @@ CONFIG_XMON=y
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
CONFIG_CRYPTO_PCBC=m
|
||||
CONFIG_CRYPTO_HMAC=y
|
||||
CONFIG_CRYPT_CRC32C_VPMSUM=m
|
||||
CONFIG_CRYPTO_MD5_PPC=m
|
||||
CONFIG_CRYPTO_MICHAEL_MIC=m
|
||||
CONFIG_CRYPTO_SHA256=y
|
||||
CONFIG_CRYPTO_TGR192=m
|
||||
CONFIG_CRYPTO_WP512=m
|
||||
CONFIG_CRYPTO_ANUBIS=m
|
||||
@ -310,6 +307,7 @@ CONFIG_CRYPTO_BLOWFISH=m
|
||||
CONFIG_CRYPTO_CAST6=m
|
||||
CONFIG_CRYPTO_KHAZAD=m
|
||||
CONFIG_CRYPTO_SALSA20=m
|
||||
CONFIG_CRYPTO_SHA1_PPC=m
|
||||
CONFIG_CRYPTO_SERPENT=m
|
||||
CONFIG_CRYPTO_TEA=m
|
||||
CONFIG_CRYPTO_TWOFISH=m
|
||||
|
@ -36,12 +36,11 @@ CONFIG_NFTL_RW=y
|
||||
CONFIG_MTD_CFI=y
|
||||
CONFIG_MTD_CFI_AMDSTD=y
|
||||
CONFIG_MTD_PHYSMAP=y
|
||||
CONFIG_IDE=y
|
||||
CONFIG_BLK_DEV_VIA82CXXX=y
|
||||
CONFIG_SCSI=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_BLK_DEV_SR=y
|
||||
CONFIG_SCSI_SPI_ATTRS=y
|
||||
CONFIG_ATA=y
|
||||
CONFIG_PATA_VIA=y
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_MD=y
|
||||
CONFIG_MD_LINEAR=y
|
||||
|
@ -13,7 +13,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/threads.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/checksum.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
@ -2,14 +2,42 @@
|
||||
#define _ASM_POWERPC_BOOK3S_32_PGALLOC_H
|
||||
|
||||
#include <linux/threads.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* For 32-bit, all levels of page tables are just drawn from get_free_page() */
|
||||
#define MAX_PGTABLE_INDEX_SIZE 0
|
||||
/*
|
||||
* 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 void __bad_pte(pmd_t *pmd);
|
||||
|
||||
extern pgd_t *pgd_alloc(struct mm_struct *mm);
|
||||
extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
|
||||
extern struct kmem_cache *pgtable_cache[];
|
||||
#define PGT_CACHE(shift) ({ \
|
||||
BUG_ON(!(shift)); \
|
||||
pgtable_cache[(shift) - 1]; \
|
||||
})
|
||||
|
||||
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
|
||||
{
|
||||
return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), GFP_KERNEL);
|
||||
}
|
||||
|
||||
static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
||||
{
|
||||
kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd);
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't have any real pmd's, and this code never triggers because
|
||||
@ -68,8 +96,12 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
|
||||
|
||||
static inline void pgtable_free(void *table, unsigned index_size)
|
||||
{
|
||||
BUG_ON(index_size); /* 32-bit doesn't use this */
|
||||
free_page((unsigned long)table);
|
||||
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 check_pgt_cache() do { } while (0)
|
||||
|
@ -8,6 +8,23 @@
|
||||
/* And here we include common definitions */
|
||||
#include <asm/pte-common.h>
|
||||
|
||||
#define PTE_INDEX_SIZE PTE_SHIFT
|
||||
#define PMD_INDEX_SIZE 0
|
||||
#define PUD_INDEX_SIZE 0
|
||||
#define PGD_INDEX_SIZE (32 - PGDIR_SHIFT)
|
||||
|
||||
#define PMD_CACHE_INDEX PMD_INDEX_SIZE
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#define PTE_TABLE_SIZE (sizeof(pte_t) << PTE_INDEX_SIZE)
|
||||
#define PMD_TABLE_SIZE 0
|
||||
#define PUD_TABLE_SIZE 0
|
||||
#define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE)
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE)
|
||||
#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE)
|
||||
|
||||
/*
|
||||
* The normal case is that PTEs are 32-bits and we have a 1-page
|
||||
* 1024-entry pgdir pointing to 1-page 1024-entry PTE pages. -- paulus
|
||||
@ -19,14 +36,10 @@
|
||||
* -Matt
|
||||
*/
|
||||
/* PGDIR_SHIFT determines what a top-level page table entry can map */
|
||||
#define PGDIR_SHIFT (PAGE_SHIFT + PTE_SHIFT)
|
||||
#define PGDIR_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE)
|
||||
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
|
||||
#define PGDIR_MASK (~(PGDIR_SIZE-1))
|
||||
|
||||
#define PTRS_PER_PTE (1 << PTE_SHIFT)
|
||||
#define PTRS_PER_PMD 1
|
||||
#define PTRS_PER_PGD (1 << (32 - PGDIR_SHIFT))
|
||||
|
||||
#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE)
|
||||
/*
|
||||
* This is the bottom of the PKMAP area with HIGHMEM or an arbitrary
|
||||
@ -82,12 +95,8 @@
|
||||
|
||||
extern unsigned long ioremap_bot;
|
||||
|
||||
/*
|
||||
* entries per page directory level: our page-table tree is two-level, so
|
||||
* we don't really have any PMD directory.
|
||||
*/
|
||||
#define PTE_TABLE_SIZE (sizeof(pte_t) << PTE_SHIFT)
|
||||
#define PGD_TABLE_SIZE (sizeof(pgd_t) << (32 - PGDIR_SHIFT))
|
||||
/* Bits to mask out from a PGD to get to the PUD page */
|
||||
#define PGD_MASKED_BITS 0
|
||||
|
||||
#define pte_ERROR(e) \
|
||||
pr_err("%s:%d: bad pte %llx.\n", __FILE__, __LINE__, \
|
||||
@ -224,7 +233,8 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
|
||||
|
||||
|
||||
static inline void __ptep_set_access_flags(struct mm_struct *mm,
|
||||
pte_t *ptep, pte_t entry)
|
||||
pte_t *ptep, pte_t entry,
|
||||
unsigned long address)
|
||||
{
|
||||
unsigned long set = pte_val(entry) &
|
||||
(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
|
||||
@ -283,15 +293,6 @@ static inline void __ptep_set_access_flags(struct mm_struct *mm,
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 3 })
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { (x).val << 3 })
|
||||
|
||||
#ifndef CONFIG_PPC_4K_PAGES
|
||||
void pgtable_cache_init(void);
|
||||
#else
|
||||
/*
|
||||
* No page table caches to initialise
|
||||
*/
|
||||
#define pgtable_cache_init() do { } while (0)
|
||||
#endif
|
||||
|
||||
extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep,
|
||||
pmd_t **pmdp);
|
||||
|
||||
|
@ -16,9 +16,6 @@
|
||||
#define H_PUD_TABLE_SIZE (sizeof(pud_t) << H_PUD_INDEX_SIZE)
|
||||
#define H_PGD_TABLE_SIZE (sizeof(pgd_t) << H_PGD_INDEX_SIZE)
|
||||
|
||||
/* With 4k base page size, hugepage PTEs go at the PMD level */
|
||||
#define MIN_HUGEPTE_SHIFT PMD_SHIFT
|
||||
|
||||
/* PTE flags to conserve for HPTE identification */
|
||||
#define _PAGE_HPTEFLAGS (H_PAGE_BUSY | H_PAGE_HASHPTE | \
|
||||
H_PAGE_F_SECOND | H_PAGE_F_GIX)
|
||||
|
@ -6,9 +6,6 @@
|
||||
#define H_PUD_INDEX_SIZE 5
|
||||
#define H_PGD_INDEX_SIZE 12
|
||||
|
||||
/* With 4k base page size, hugepage PTEs go at the PMD level */
|
||||
#define MIN_HUGEPTE_SHIFT PAGE_SHIFT
|
||||
|
||||
#define H_PAGE_COMBO 0x00001000 /* this is a combo 4k page */
|
||||
#define H_PAGE_4K_PFN 0x00002000 /* PFN is for a single 4k page */
|
||||
/*
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef _ASM_POWERPC_BOOK3S_64_HUGETLB_RADIX_H
|
||||
#define _ASM_POWERPC_BOOK3S_64_HUGETLB_RADIX_H
|
||||
#ifndef _ASM_POWERPC_BOOK3S_64_HUGETLB_H
|
||||
#define _ASM_POWERPC_BOOK3S_64_HUGETLB_H
|
||||
/*
|
||||
* For radix we want generic code to handle hugetlb. But then if we want
|
||||
* both hash and radix to be enabled together we need to workaround the
|
||||
@ -21,9 +21,33 @@ static inline int hstate_get_psize(struct hstate *hstate)
|
||||
return MMU_PAGE_2M;
|
||||
else if (shift == mmu_psize_defs[MMU_PAGE_1G].shift)
|
||||
return MMU_PAGE_1G;
|
||||
else if (shift == mmu_psize_defs[MMU_PAGE_16M].shift)
|
||||
return MMU_PAGE_16M;
|
||||
else if (shift == mmu_psize_defs[MMU_PAGE_16G].shift)
|
||||
return MMU_PAGE_16G;
|
||||
else {
|
||||
WARN(1, "Wrong huge page shift\n");
|
||||
return mmu_virtual_psize;
|
||||
}
|
||||
}
|
||||
|
||||
#define arch_make_huge_pte arch_make_huge_pte
|
||||
static inline pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma,
|
||||
struct page *page, int writable)
|
||||
{
|
||||
unsigned long page_shift;
|
||||
|
||||
if (!cpu_has_feature(CPU_FTR_POWER9_DD1))
|
||||
return entry;
|
||||
|
||||
page_shift = huge_page_shift(hstate_vma(vma));
|
||||
/*
|
||||
* We don't support 1G hugetlb pages yet.
|
||||
*/
|
||||
VM_WARN_ON(page_shift == mmu_psize_defs[MMU_PAGE_1G].shift);
|
||||
if (page_shift == mmu_psize_defs[MMU_PAGE_2M].shift)
|
||||
return __pte(pte_val(entry) | _PAGE_LARGE);
|
||||
else
|
||||
return entry;
|
||||
}
|
||||
#endif
|
@ -26,6 +26,11 @@
|
||||
#define _RPAGE_SW1 0x00800
|
||||
#define _RPAGE_SW2 0x00400
|
||||
#define _RPAGE_SW3 0x00200
|
||||
#define _RPAGE_RSV1 0x1000000000000000UL
|
||||
#define _RPAGE_RSV2 0x0800000000000000UL
|
||||
#define _RPAGE_RSV3 0x0400000000000000UL
|
||||
#define _RPAGE_RSV4 0x0200000000000000UL
|
||||
|
||||
#ifdef CONFIG_MEM_SOFT_DIRTY
|
||||
#define _PAGE_SOFT_DIRTY _RPAGE_SW3 /* software: software dirty tracking */
|
||||
#else
|
||||
@ -33,6 +38,11 @@
|
||||
#endif
|
||||
#define _PAGE_SPECIAL _RPAGE_SW2 /* software: special page */
|
||||
|
||||
/*
|
||||
* For P9 DD1 only, we need to track whether the pte's huge.
|
||||
*/
|
||||
#define _PAGE_LARGE _RPAGE_RSV1
|
||||
|
||||
|
||||
#define _PAGE_PTE (1ul << 62) /* distinguishes PTEs from pointers */
|
||||
#define _PAGE_PRESENT (1ul << 63) /* pte contains a translation */
|
||||
@ -568,10 +578,11 @@ static inline bool check_pte_access(unsigned long access, unsigned long ptev)
|
||||
*/
|
||||
|
||||
static inline void __ptep_set_access_flags(struct mm_struct *mm,
|
||||
pte_t *ptep, pte_t entry)
|
||||
pte_t *ptep, pte_t entry,
|
||||
unsigned long address)
|
||||
{
|
||||
if (radix_enabled())
|
||||
return radix__ptep_set_access_flags(mm, ptep, entry);
|
||||
return radix__ptep_set_access_flags(mm, ptep, entry, address);
|
||||
return hash__ptep_set_access_flags(ptep, entry);
|
||||
}
|
||||
|
||||
@ -789,9 +800,6 @@ extern struct page *pgd_page(pgd_t pgd);
|
||||
#define pgd_ERROR(e) \
|
||||
pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
|
||||
|
||||
void pgtable_cache_add(unsigned shift, void (*ctor)(void *));
|
||||
void pgtable_cache_init(void);
|
||||
|
||||
static inline int map_kernel_page(unsigned long ea, unsigned long pa,
|
||||
unsigned long flags)
|
||||
{
|
||||
|
@ -140,19 +140,20 @@ static inline unsigned long radix__pte_update(struct mm_struct *mm,
|
||||
unsigned long new_pte;
|
||||
|
||||
old_pte = __radix_pte_update(ptep, ~0, 0);
|
||||
asm volatile("ptesync" : : : "memory");
|
||||
/*
|
||||
* new value of pte
|
||||
*/
|
||||
new_pte = (old_pte | set) & ~clr;
|
||||
|
||||
/*
|
||||
* For now let's do heavy pid flush
|
||||
* radix__flush_tlb_page_psize(mm, addr, mmu_virtual_psize);
|
||||
* If we are trying to clear the pte, we can skip
|
||||
* the below sequence and batch the tlb flush. The
|
||||
* tlb flush batching is done by mmu gather code
|
||||
*/
|
||||
radix__flush_tlb_mm(mm);
|
||||
|
||||
__radix_pte_update(ptep, 0, new_pte);
|
||||
if (new_pte) {
|
||||
asm volatile("ptesync" : : : "memory");
|
||||
radix__flush_tlb_pte_p9_dd1(old_pte, mm, addr);
|
||||
__radix_pte_update(ptep, 0, new_pte);
|
||||
}
|
||||
} else
|
||||
old_pte = __radix_pte_update(ptep, clr, set);
|
||||
asm volatile("ptesync" : : : "memory");
|
||||
@ -167,7 +168,8 @@ static inline unsigned long radix__pte_update(struct mm_struct *mm,
|
||||
* function doesn't need to invalidate tlb.
|
||||
*/
|
||||
static inline void radix__ptep_set_access_flags(struct mm_struct *mm,
|
||||
pte_t *ptep, pte_t entry)
|
||||
pte_t *ptep, pte_t entry,
|
||||
unsigned long address)
|
||||
{
|
||||
|
||||
unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED |
|
||||
@ -183,13 +185,7 @@ static inline void radix__ptep_set_access_flags(struct mm_struct *mm,
|
||||
* new value of pte
|
||||
*/
|
||||
new_pte = old_pte | set;
|
||||
|
||||
/*
|
||||
* For now let's do heavy pid flush
|
||||
* radix__flush_tlb_page_psize(mm, addr, mmu_virtual_psize);
|
||||
*/
|
||||
radix__flush_tlb_mm(mm);
|
||||
|
||||
radix__flush_tlb_pte_p9_dd1(old_pte, mm, address);
|
||||
__radix_pte_update(ptep, 0, new_pte);
|
||||
} else
|
||||
__radix_pte_update(ptep, 0, set);
|
||||
@ -243,6 +239,8 @@ static inline int radix__pmd_trans_huge(pmd_t pmd)
|
||||
|
||||
static inline pmd_t radix__pmd_mkhuge(pmd_t pmd)
|
||||
{
|
||||
if (cpu_has_feature(CPU_FTR_POWER9_DD1))
|
||||
return __pmd(pmd_val(pmd) | _PAGE_PTE | _PAGE_LARGE);
|
||||
return __pmd(pmd_val(pmd) | _PAGE_PTE);
|
||||
}
|
||||
static inline void radix__pmdp_huge_split_prepare(struct vm_area_struct *vma,
|
||||
|
@ -42,4 +42,6 @@ extern void radix__flush_tlb_lpid_va(unsigned long lpid, unsigned long gpa,
|
||||
unsigned long page_size);
|
||||
extern void radix__flush_tlb_lpid(unsigned long lpid);
|
||||
extern void radix__flush_tlb_all(void);
|
||||
extern void radix__flush_tlb_pte_p9_dd1(unsigned long old_pte, struct mm_struct *mm,
|
||||
unsigned long address);
|
||||
#endif
|
||||
|
@ -20,12 +20,15 @@
|
||||
#endif
|
||||
#else /* CONFIG_PPC64 */
|
||||
#define L1_CACHE_SHIFT 7
|
||||
#define IFETCH_ALIGN_SHIFT 4 /* POWER8,9 */
|
||||
#endif
|
||||
|
||||
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
|
||||
|
||||
#define SMP_CACHE_BYTES L1_CACHE_BYTES
|
||||
|
||||
#define IFETCH_ALIGN_BYTES (1 << IFETCH_ALIGN_SHIFT)
|
||||
|
||||
#if defined(__powerpc64__) && !defined(__ASSEMBLY__)
|
||||
struct ppc64_caches {
|
||||
u32 dsize; /* L1 d-cache size */
|
||||
|
@ -7,6 +7,71 @@
|
||||
#include <asm/asm-compat.h>
|
||||
#include <linux/bug.h>
|
||||
|
||||
#ifdef __BIG_ENDIAN
|
||||
#define BITOFF_CAL(size, off) ((sizeof(u32) - size - off) * BITS_PER_BYTE)
|
||||
#else
|
||||
#define BITOFF_CAL(size, off) (off * BITS_PER_BYTE)
|
||||
#endif
|
||||
|
||||
#define XCHG_GEN(type, sfx, cl) \
|
||||
static inline u32 __xchg_##type##sfx(volatile void *p, u32 val) \
|
||||
{ \
|
||||
unsigned int prev, prev_mask, tmp, bitoff, off; \
|
||||
\
|
||||
off = (unsigned long)p % sizeof(u32); \
|
||||
bitoff = BITOFF_CAL(sizeof(type), off); \
|
||||
p -= off; \
|
||||
val <<= bitoff; \
|
||||
prev_mask = (u32)(type)-1 << bitoff; \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
"1: lwarx %0,0,%3\n" \
|
||||
" andc %1,%0,%5\n" \
|
||||
" or %1,%1,%4\n" \
|
||||
PPC405_ERR77(0,%3) \
|
||||
" stwcx. %1,0,%3\n" \
|
||||
" bne- 1b\n" \
|
||||
: "=&r" (prev), "=&r" (tmp), "+m" (*(u32*)p) \
|
||||
: "r" (p), "r" (val), "r" (prev_mask) \
|
||||
: "cc", cl); \
|
||||
\
|
||||
return prev >> bitoff; \
|
||||
}
|
||||
|
||||
#define CMPXCHG_GEN(type, sfx, br, br2, cl) \
|
||||
static inline \
|
||||
u32 __cmpxchg_##type##sfx(volatile void *p, u32 old, u32 new) \
|
||||
{ \
|
||||
unsigned int prev, prev_mask, tmp, bitoff, off; \
|
||||
\
|
||||
off = (unsigned long)p % sizeof(u32); \
|
||||
bitoff = BITOFF_CAL(sizeof(type), off); \
|
||||
p -= off; \
|
||||
old <<= bitoff; \
|
||||
new <<= bitoff; \
|
||||
prev_mask = (u32)(type)-1 << bitoff; \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
br \
|
||||
"1: lwarx %0,0,%3\n" \
|
||||
" and %1,%0,%6\n" \
|
||||
" cmpw 0,%1,%4\n" \
|
||||
" bne- 2f\n" \
|
||||
" andc %1,%0,%6\n" \
|
||||
" or %1,%1,%5\n" \
|
||||
PPC405_ERR77(0,%3) \
|
||||
" stwcx. %1,0,%3\n" \
|
||||
" bne- 1b\n" \
|
||||
br2 \
|
||||
"\n" \
|
||||
"2:" \
|
||||
: "=&r" (prev), "=&r" (tmp), "+m" (*(u32*)p) \
|
||||
: "r" (p), "r" (old), "r" (new), "r" (prev_mask) \
|
||||
: "cc", cl); \
|
||||
\
|
||||
return prev >> bitoff; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Atomic exchange
|
||||
*
|
||||
@ -14,6 +79,11 @@
|
||||
* the previous value stored there.
|
||||
*/
|
||||
|
||||
XCHG_GEN(u8, _local, "memory");
|
||||
XCHG_GEN(u8, _relaxed, "cc");
|
||||
XCHG_GEN(u16, _local, "memory");
|
||||
XCHG_GEN(u16, _relaxed, "cc");
|
||||
|
||||
static __always_inline unsigned long
|
||||
__xchg_u32_local(volatile void *p, unsigned long val)
|
||||
{
|
||||
@ -85,9 +155,13 @@ __xchg_u64_relaxed(u64 *p, unsigned long val)
|
||||
#endif
|
||||
|
||||
static __always_inline unsigned long
|
||||
__xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
|
||||
__xchg_local(void *ptr, unsigned long x, unsigned int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
return __xchg_u8_local(ptr, x);
|
||||
case 2:
|
||||
return __xchg_u16_local(ptr, x);
|
||||
case 4:
|
||||
return __xchg_u32_local(ptr, x);
|
||||
#ifdef CONFIG_PPC64
|
||||
@ -103,6 +177,10 @@ static __always_inline unsigned long
|
||||
__xchg_relaxed(void *ptr, unsigned long x, unsigned int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
return __xchg_u8_relaxed(ptr, x);
|
||||
case 2:
|
||||
return __xchg_u16_relaxed(ptr, x);
|
||||
case 4:
|
||||
return __xchg_u32_relaxed(ptr, x);
|
||||
#ifdef CONFIG_PPC64
|
||||
@ -131,6 +209,15 @@ __xchg_relaxed(void *ptr, unsigned long x, unsigned int size)
|
||||
* and return the old value of *p.
|
||||
*/
|
||||
|
||||
CMPXCHG_GEN(u8, , PPC_ATOMIC_ENTRY_BARRIER, PPC_ATOMIC_EXIT_BARRIER, "memory");
|
||||
CMPXCHG_GEN(u8, _local, , , "memory");
|
||||
CMPXCHG_GEN(u8, _acquire, , PPC_ACQUIRE_BARRIER, "memory");
|
||||
CMPXCHG_GEN(u8, _relaxed, , , "cc");
|
||||
CMPXCHG_GEN(u16, , PPC_ATOMIC_ENTRY_BARRIER, PPC_ATOMIC_EXIT_BARRIER, "memory");
|
||||
CMPXCHG_GEN(u16, _local, , , "memory");
|
||||
CMPXCHG_GEN(u16, _acquire, , PPC_ACQUIRE_BARRIER, "memory");
|
||||
CMPXCHG_GEN(u16, _relaxed, , , "cc");
|
||||
|
||||
static __always_inline unsigned long
|
||||
__cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
|
||||
{
|
||||
@ -316,6 +403,10 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
|
||||
unsigned int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
return __cmpxchg_u8(ptr, old, new);
|
||||
case 2:
|
||||
return __cmpxchg_u16(ptr, old, new);
|
||||
case 4:
|
||||
return __cmpxchg_u32(ptr, old, new);
|
||||
#ifdef CONFIG_PPC64
|
||||
@ -328,10 +419,14 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
|
||||
}
|
||||
|
||||
static __always_inline unsigned long
|
||||
__cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
|
||||
__cmpxchg_local(void *ptr, unsigned long old, unsigned long new,
|
||||
unsigned int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
return __cmpxchg_u8_local(ptr, old, new);
|
||||
case 2:
|
||||
return __cmpxchg_u16_local(ptr, old, new);
|
||||
case 4:
|
||||
return __cmpxchg_u32_local(ptr, old, new);
|
||||
#ifdef CONFIG_PPC64
|
||||
@ -348,6 +443,10 @@ __cmpxchg_relaxed(void *ptr, unsigned long old, unsigned long new,
|
||||
unsigned int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
return __cmpxchg_u8_relaxed(ptr, old, new);
|
||||
case 2:
|
||||
return __cmpxchg_u16_relaxed(ptr, old, new);
|
||||
case 4:
|
||||
return __cmpxchg_u32_relaxed(ptr, old, new);
|
||||
#ifdef CONFIG_PPC64
|
||||
@ -364,6 +463,10 @@ __cmpxchg_acquire(void *ptr, unsigned long old, unsigned long new,
|
||||
unsigned int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
return __cmpxchg_u8_acquire(ptr, old, new);
|
||||
case 2:
|
||||
return __cmpxchg_u16_acquire(ptr, old, new);
|
||||
case 4:
|
||||
return __cmpxchg_u32_acquire(ptr, old, new);
|
||||
#ifdef CONFIG_PPC64
|
||||
|
@ -10,7 +10,7 @@ struct pt_regs;
|
||||
|
||||
extern struct dentry *powerpc_debugfs_root;
|
||||
|
||||
#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
|
||||
#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC_CORE)
|
||||
|
||||
extern int (*__debugger)(struct pt_regs *regs);
|
||||
extern int (*__debugger_ipi)(struct pt_regs *regs);
|
||||
|
@ -23,10 +23,8 @@
|
||||
"4: li %1,%3\n" \
|
||||
"b 3b\n" \
|
||||
".previous\n" \
|
||||
".section __ex_table,\"a\"\n" \
|
||||
".align 3\n" \
|
||||
PPC_LONG "1b,4b,2b,4b\n" \
|
||||
".previous" \
|
||||
EX_TABLE(1b, 4b) \
|
||||
EX_TABLE(2b, 4b) \
|
||||
: "=&r" (oldval), "=&r" (ret) \
|
||||
: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
|
||||
: "cr0", "memory")
|
||||
@ -104,11 +102,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||
"3: .section .fixup,\"ax\"\n\
|
||||
4: li %0,%6\n\
|
||||
b 3b\n\
|
||||
.previous\n\
|
||||
.section __ex_table,\"a\"\n\
|
||||
.align 3\n\
|
||||
" PPC_LONG "1b,4b,2b,4b\n\
|
||||
.previous" \
|
||||
.previous\n"
|
||||
EX_TABLE(1b, 4b)
|
||||
EX_TABLE(2b, 4b)
|
||||
: "+r" (ret), "=&r" (prev), "+m" (*uaddr)
|
||||
: "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
|
||||
: "cc", "memory");
|
||||
|
@ -95,12 +95,12 @@ end_##sname:
|
||||
|
||||
#define __FIXED_SECTION_ENTRY_BEGIN(sname, name, __align) \
|
||||
USE_FIXED_SECTION(sname); \
|
||||
.align __align; \
|
||||
.balign __align; \
|
||||
.global name; \
|
||||
name:
|
||||
|
||||
#define FIXED_SECTION_ENTRY_BEGIN(sname, name) \
|
||||
__FIXED_SECTION_ENTRY_BEGIN(sname, name, 0)
|
||||
__FIXED_SECTION_ENTRY_BEGIN(sname, name, IFETCH_ALIGN_BYTES)
|
||||
|
||||
#define FIXED_SECTION_ENTRY_BEGIN_LOCATION(sname, name, start) \
|
||||
USE_FIXED_SECTION(sname); \
|
||||
@ -203,9 +203,9 @@ end_##sname:
|
||||
#define EXC_VIRT_END(name, start, end) \
|
||||
FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##name, end)
|
||||
|
||||
#define EXC_COMMON_BEGIN(name) \
|
||||
#define EXC_COMMON_BEGIN(name) \
|
||||
USE_TEXT_SECTION(); \
|
||||
.align 7; \
|
||||
.balign IFETCH_ALIGN_BYTES; \
|
||||
.global name; \
|
||||
DEFINE_FIXED_SYMBOL(name); \
|
||||
name:
|
||||
|
@ -9,7 +9,7 @@ extern struct kmem_cache *hugepte_cache;
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
|
||||
#include <asm/book3s/64/hugetlb-radix.h>
|
||||
#include <asm/book3s/64/hugetlb.h>
|
||||
/*
|
||||
* This should work for other subarchs too. But right now we use the
|
||||
* new format only for 64bit book3s
|
||||
@ -51,12 +51,20 @@ static inline void __local_flush_hugetlb_page(struct vm_area_struct *vma,
|
||||
static inline pte_t *hugepd_page(hugepd_t hpd)
|
||||
{
|
||||
BUG_ON(!hugepd_ok(hpd));
|
||||
#ifdef CONFIG_PPC_8xx
|
||||
return (pte_t *)__va(hpd.pd & ~(_PMD_PAGE_MASK | _PMD_PRESENT_MASK));
|
||||
#else
|
||||
return (pte_t *)((hpd.pd & ~HUGEPD_SHIFT_MASK) | PD_HUGE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline unsigned int hugepd_shift(hugepd_t hpd)
|
||||
{
|
||||
#ifdef CONFIG_PPC_8xx
|
||||
return ((hpd.pd & _PMD_PAGE_MASK) >> 1) + 17;
|
||||
#else
|
||||
return hpd.pd & HUGEPD_SHIFT_MASK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
@ -99,7 +107,15 @@ static inline int is_hugepage_only_range(struct mm_struct *mm,
|
||||
|
||||
void book3e_hugetlb_preload(struct vm_area_struct *vma, unsigned long ea,
|
||||
pte_t pte);
|
||||
#ifdef CONFIG_PPC_8xx
|
||||
static inline void flush_hugetlb_page(struct vm_area_struct *vma,
|
||||
unsigned long vmaddr)
|
||||
{
|
||||
flush_tlb_page(vma, vmaddr);
|
||||
}
|
||||
#else
|
||||
void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
|
||||
#endif
|
||||
|
||||
void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
|
||||
unsigned long end, unsigned long floor,
|
||||
@ -205,7 +221,8 @@ static inline pte_t *hugepte_offset(hugepd_t hpd, unsigned long addr,
|
||||
* are reserved early in the boot process by memblock instead of via
|
||||
* the .dts as on IBM platforms.
|
||||
*/
|
||||
#if defined(CONFIG_HUGETLB_PAGE) && defined(CONFIG_PPC_FSL_BOOK3E)
|
||||
#if defined(CONFIG_HUGETLB_PAGE) && (defined(CONFIG_PPC_FSL_BOOK3E) || \
|
||||
defined(CONFIG_PPC_8xx))
|
||||
extern void __init reserve_hugetlb_gpages(void);
|
||||
#else
|
||||
static inline void reserve_hugetlb_gpages(void)
|
||||
|
@ -275,7 +275,9 @@
|
||||
#define H_COP 0x304
|
||||
#define H_GET_MPP_X 0x314
|
||||
#define H_SET_MODE 0x31C
|
||||
#define MAX_HCALL_OPCODE H_SET_MODE
|
||||
#define H_CLEAR_HPT 0x358
|
||||
#define H_SIGNAL_SYS_RESET 0x380
|
||||
#define MAX_HCALL_OPCODE H_SIGNAL_SYS_RESET
|
||||
|
||||
/* H_VIOCTL functions */
|
||||
#define H_GET_VIOA_DUMP_SIZE 0x01
|
||||
@ -306,6 +308,11 @@
|
||||
#define H_SET_MODE_RESOURCE_ADDR_TRANS_MODE 3
|
||||
#define H_SET_MODE_RESOURCE_LE 4
|
||||
|
||||
/* Values for argument to H_SIGNAL_SYS_RESET */
|
||||
#define H_SIGNAL_SYS_RESET_ALL -1
|
||||
#define H_SIGNAL_SYS_RESET_ALL_OTHERS -2
|
||||
/* >= 0 values are CPU number */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/**
|
||||
@ -412,27 +419,6 @@ static inline unsigned int get_longbusy_msecs(int longbusy_rc)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
extern int CMO_PrPSP;
|
||||
extern int CMO_SecPSP;
|
||||
extern unsigned long CMO_PageSize;
|
||||
|
||||
static inline int cmo_get_primary_psp(void)
|
||||
{
|
||||
return CMO_PrPSP;
|
||||
}
|
||||
|
||||
static inline int cmo_get_secondary_psp(void)
|
||||
{
|
||||
return CMO_SecPSP;
|
||||
}
|
||||
|
||||
static inline unsigned long cmo_get_page_size(void)
|
||||
{
|
||||
return CMO_PageSize;
|
||||
}
|
||||
#endif /* CONFIG_PPC_PSERIES */
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_POWERPC_HVCALL_H */
|
||||
|
@ -33,6 +33,7 @@ extern struct pci_dev *isa_bridge_pcidev;
|
||||
#include <asm/synch.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/ppc_asm.h>
|
||||
|
||||
#include <asm-generic/iomap.h>
|
||||
|
||||
@ -458,13 +459,10 @@ static inline unsigned int name(unsigned int port) \
|
||||
"5: li %0,-1\n" \
|
||||
" b 4b\n" \
|
||||
".previous\n" \
|
||||
".section __ex_table,\"a\"\n" \
|
||||
" .align 2\n" \
|
||||
" .long 0b,5b\n" \
|
||||
" .long 1b,5b\n" \
|
||||
" .long 2b,5b\n" \
|
||||
" .long 3b,5b\n" \
|
||||
".previous" \
|
||||
EX_TABLE(0b, 5b) \
|
||||
EX_TABLE(1b, 5b) \
|
||||
EX_TABLE(2b, 5b) \
|
||||
EX_TABLE(3b, 5b) \
|
||||
: "=&r" (x) \
|
||||
: "r" (port + _IO_BASE) \
|
||||
: "memory"); \
|
||||
@ -479,11 +477,8 @@ static inline void name(unsigned int val, unsigned int port) \
|
||||
"0:" op " %0,0,%1\n" \
|
||||
"1: sync\n" \
|
||||
"2:\n" \
|
||||
".section __ex_table,\"a\"\n" \
|
||||
" .align 2\n" \
|
||||
" .long 0b,2b\n" \
|
||||
" .long 1b,2b\n" \
|
||||
".previous" \
|
||||
EX_TABLE(0b, 2b) \
|
||||
EX_TABLE(1b, 2b) \
|
||||
: : "r" (val), "r" (port + _IO_BASE) \
|
||||
: "memory"); \
|
||||
}
|
||||
|
@ -53,7 +53,7 @@
|
||||
|
||||
typedef void (*crash_shutdown_t)(void);
|
||||
|
||||
#ifdef CONFIG_KEXEC
|
||||
#ifdef CONFIG_KEXEC_CORE
|
||||
|
||||
/*
|
||||
* This function is responsible for capturing register states if coming
|
||||
@ -91,7 +91,17 @@ static inline bool kdump_in_progress(void)
|
||||
return crashing_cpu >= 0;
|
||||
}
|
||||
|
||||
#else /* !CONFIG_KEXEC */
|
||||
#ifdef CONFIG_KEXEC_FILE
|
||||
extern struct kexec_file_ops kexec_elf64_ops;
|
||||
|
||||
int setup_purgatory(struct kimage *image, const void *slave_code,
|
||||
const void *fdt, unsigned long kernel_load_addr,
|
||||
unsigned long fdt_load_addr);
|
||||
int setup_new_fdt(void *fdt, unsigned long initrd_load_addr,
|
||||
unsigned long initrd_len, const char *cmdline);
|
||||
#endif /* CONFIG_KEXEC_FILE */
|
||||
|
||||
#else /* !CONFIG_KEXEC_CORE */
|
||||
static inline void crash_kexec_secondary(struct pt_regs *regs) { }
|
||||
|
||||
static inline int overlaps_crashkernel(unsigned long start, unsigned long size)
|
||||
@ -116,7 +126,7 @@ static inline bool kdump_in_progress(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_KEXEC */
|
||||
#endif /* CONFIG_KEXEC_CORE */
|
||||
#endif /* ! __ASSEMBLY__ */
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_POWERPC_KEXEC_H */
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <asm/probes.h>
|
||||
#include <asm/code-patching.h>
|
||||
|
||||
#ifdef CONFIG_KPROBES
|
||||
#define __ARCH_WANT_KPROBES_INSN_SLOT
|
||||
|
||||
struct pt_regs;
|
||||
@ -127,5 +128,11 @@ struct kprobe_ctlblk {
|
||||
extern int kprobe_exceptions_notify(struct notifier_block *self,
|
||||
unsigned long val, void *data);
|
||||
extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
|
||||
extern int kprobe_handler(struct pt_regs *regs);
|
||||
extern int kprobe_post_handler(struct pt_regs *regs);
|
||||
#else
|
||||
static inline int kprobe_handler(struct pt_regs *regs) { return 0; }
|
||||
static inline int kprobe_post_handler(struct pt_regs *regs) { return 0; }
|
||||
#endif /* CONFIG_KPROBES */
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_POWERPC_KPROBES_H */
|
||||
|
@ -183,7 +183,7 @@ struct machdep_calls {
|
||||
*/
|
||||
void (*machine_shutdown)(void);
|
||||
|
||||
#ifdef CONFIG_KEXEC
|
||||
#ifdef CONFIG_KEXEC_CORE
|
||||
void (*kexec_cpu_down)(int crash_shutdown, int secondary);
|
||||
|
||||
/* Called to do what every setup is needed on image and the
|
||||
@ -198,7 +198,7 @@ struct machdep_calls {
|
||||
* no return.
|
||||
*/
|
||||
void (*machine_kexec)(struct kimage *image);
|
||||
#endif /* CONFIG_KEXEC */
|
||||
#endif /* CONFIG_KEXEC_CORE */
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
/* These are called to disable and enable, respectively, IRQs when
|
||||
|
@ -172,6 +172,41 @@ typedef struct {
|
||||
|
||||
#define PHYS_IMMR_BASE (mfspr(SPRN_IMMR) & 0xfff80000)
|
||||
#define VIRT_IMMR_BASE (__fix_to_virt(FIX_IMMR_BASE))
|
||||
|
||||
/* Page size definitions, common between 32 and 64-bit
|
||||
*
|
||||
* shift : is the "PAGE_SHIFT" value for that page size
|
||||
* penc : is the pte encoding mask
|
||||
*
|
||||
*/
|
||||
struct mmu_psize_def {
|
||||
unsigned int shift; /* number of bits */
|
||||
unsigned int enc; /* PTE encoding */
|
||||
unsigned int ind; /* Corresponding indirect page size shift */
|
||||
unsigned int flags;
|
||||
#define MMU_PAGE_SIZE_DIRECT 0x1 /* Supported as a direct size */
|
||||
#define MMU_PAGE_SIZE_INDIRECT 0x2 /* Supported as an indirect size */
|
||||
};
|
||||
|
||||
extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
|
||||
|
||||
static inline int shift_to_mmu_psize(unsigned int shift)
|
||||
{
|
||||
int psize;
|
||||
|
||||
for (psize = 0; psize < MMU_PAGE_COUNT; ++psize)
|
||||
if (mmu_psize_defs[psize].shift == shift)
|
||||
return psize;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
|
||||
{
|
||||
if (mmu_psize_defs[mmu_psize].shift)
|
||||
return mmu_psize_defs[mmu_psize].shift;
|
||||
BUG();
|
||||
}
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#if defined(CONFIG_PPC_4K_PAGES)
|
||||
|
@ -275,19 +275,20 @@ static inline bool early_radix_enabled(void)
|
||||
#define MMU_PAGE_64K 2
|
||||
#define MMU_PAGE_64K_AP 3 /* "Admixed pages" (hash64 only) */
|
||||
#define MMU_PAGE_256K 4
|
||||
#define MMU_PAGE_1M 5
|
||||
#define MMU_PAGE_2M 6
|
||||
#define MMU_PAGE_4M 7
|
||||
#define MMU_PAGE_8M 8
|
||||
#define MMU_PAGE_16M 9
|
||||
#define MMU_PAGE_64M 10
|
||||
#define MMU_PAGE_256M 11
|
||||
#define MMU_PAGE_1G 12
|
||||
#define MMU_PAGE_16G 13
|
||||
#define MMU_PAGE_64G 14
|
||||
#define MMU_PAGE_512K 5
|
||||
#define MMU_PAGE_1M 6
|
||||
#define MMU_PAGE_2M 7
|
||||
#define MMU_PAGE_4M 8
|
||||
#define MMU_PAGE_8M 9
|
||||
#define MMU_PAGE_16M 10
|
||||
#define MMU_PAGE_64M 11
|
||||
#define MMU_PAGE_256M 12
|
||||
#define MMU_PAGE_1G 13
|
||||
#define MMU_PAGE_16G 14
|
||||
#define MMU_PAGE_64G 15
|
||||
|
||||
/* N.B. we need to change the type of hpte_page_sizes if this gets to be > 16 */
|
||||
#define MMU_PAGE_COUNT 15
|
||||
#define MMU_PAGE_COUNT 16
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
#include <asm/book3s/64/mmu.h>
|
||||
|
@ -19,16 +19,18 @@ extern void destroy_context(struct mm_struct *mm);
|
||||
struct mm_iommu_table_group_mem_t;
|
||||
|
||||
extern int isolate_lru_page(struct page *page); /* from internal.h */
|
||||
extern bool mm_iommu_preregistered(void);
|
||||
extern long mm_iommu_get(unsigned long ua, unsigned long entries,
|
||||
extern bool mm_iommu_preregistered(struct mm_struct *mm);
|
||||
extern long mm_iommu_get(struct mm_struct *mm,
|
||||
unsigned long ua, unsigned long entries,
|
||||
struct mm_iommu_table_group_mem_t **pmem);
|
||||
extern long mm_iommu_put(struct mm_iommu_table_group_mem_t *mem);
|
||||
extern void mm_iommu_init(mm_context_t *ctx);
|
||||
extern void mm_iommu_cleanup(mm_context_t *ctx);
|
||||
extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup(unsigned long ua,
|
||||
unsigned long size);
|
||||
extern struct mm_iommu_table_group_mem_t *mm_iommu_find(unsigned long ua,
|
||||
unsigned long entries);
|
||||
extern long mm_iommu_put(struct mm_struct *mm,
|
||||
struct mm_iommu_table_group_mem_t *mem);
|
||||
extern void mm_iommu_init(struct mm_struct *mm);
|
||||
extern void mm_iommu_cleanup(struct mm_struct *mm);
|
||||
extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup(struct mm_struct *mm,
|
||||
unsigned long ua, unsigned long size);
|
||||
extern struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm,
|
||||
unsigned long ua, unsigned long entries);
|
||||
extern long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem,
|
||||
unsigned long ua, unsigned long *hpa);
|
||||
extern long mm_iommu_mapped_inc(struct mm_iommu_table_group_mem_t *mem);
|
||||
|
@ -90,10 +90,6 @@ static inline int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sec
|
||||
}
|
||||
#endif
|
||||
|
||||
struct exception_table_entry;
|
||||
void sort_ex_table(struct exception_table_entry *start,
|
||||
struct exception_table_entry *finish);
|
||||
|
||||
#if defined(CONFIG_MODVERSIONS) && defined(CONFIG_PPC64)
|
||||
#define ARCH_RELOCATES_KCRCTAB
|
||||
#define reloc_start PHYSICAL_START
|
||||
|
@ -2,14 +2,42 @@
|
||||
#define _ASM_POWERPC_PGALLOC_32_H
|
||||
|
||||
#include <linux/threads.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* For 32-bit, all levels of page tables are just drawn from get_free_page() */
|
||||
#define MAX_PGTABLE_INDEX_SIZE 0
|
||||
/*
|
||||
* 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 void __bad_pte(pmd_t *pmd);
|
||||
|
||||
extern pgd_t *pgd_alloc(struct mm_struct *mm);
|
||||
extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
|
||||
extern struct kmem_cache *pgtable_cache[];
|
||||
#define PGT_CACHE(shift) ({ \
|
||||
BUG_ON(!(shift)); \
|
||||
pgtable_cache[(shift) - 1]; \
|
||||
})
|
||||
|
||||
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
|
||||
{
|
||||
return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), GFP_KERNEL);
|
||||
}
|
||||
|
||||
static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
||||
{
|
||||
kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd);
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't have any real pmd's, and this code never triggers because
|
||||
@ -68,8 +96,12 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
|
||||
|
||||
static inline void pgtable_free(void *table, unsigned index_size)
|
||||
{
|
||||
BUG_ON(index_size); /* 32-bit doesn't use this */
|
||||
free_page((unsigned long)table);
|
||||
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 check_pgt_cache() do { } while (0)
|
||||
|
@ -16,6 +16,23 @@ extern int icache_44x_need_flush;
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#define PTE_INDEX_SIZE PTE_SHIFT
|
||||
#define PMD_INDEX_SIZE 0
|
||||
#define PUD_INDEX_SIZE 0
|
||||
#define PGD_INDEX_SIZE (32 - PGDIR_SHIFT)
|
||||
|
||||
#define PMD_CACHE_INDEX PMD_INDEX_SIZE
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#define PTE_TABLE_SIZE (sizeof(pte_t) << PTE_INDEX_SIZE)
|
||||
#define PMD_TABLE_SIZE 0
|
||||
#define PUD_TABLE_SIZE 0
|
||||
#define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE)
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE)
|
||||
#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE)
|
||||
|
||||
/*
|
||||
* The normal case is that PTEs are 32-bits and we have a 1-page
|
||||
* 1024-entry pgdir pointing to 1-page 1024-entry PTE pages. -- paulus
|
||||
@ -27,22 +44,12 @@ extern int icache_44x_need_flush;
|
||||
* -Matt
|
||||
*/
|
||||
/* PGDIR_SHIFT determines what a top-level page table entry can map */
|
||||
#define PGDIR_SHIFT (PAGE_SHIFT + PTE_SHIFT)
|
||||
#define PGDIR_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE)
|
||||
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
|
||||
#define PGDIR_MASK (~(PGDIR_SIZE-1))
|
||||
|
||||
/*
|
||||
* entries per page directory level: our page-table tree is two-level, so
|
||||
* we don't really have any PMD directory.
|
||||
*/
|
||||
#ifndef __ASSEMBLY__
|
||||
#define PTE_TABLE_SIZE (sizeof(pte_t) << PTE_SHIFT)
|
||||
#define PGD_TABLE_SIZE (sizeof(pgd_t) << (32 - PGDIR_SHIFT))
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#define PTRS_PER_PTE (1 << PTE_SHIFT)
|
||||
#define PTRS_PER_PMD 1
|
||||
#define PTRS_PER_PGD (1 << (32 - PGDIR_SHIFT))
|
||||
/* Bits to mask out from a PGD to get to the PUD page */
|
||||
#define PGD_MASKED_BITS 0
|
||||
|
||||
#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE)
|
||||
#define FIRST_USER_ADDRESS 0UL
|
||||
@ -268,7 +275,8 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
|
||||
|
||||
|
||||
static inline void __ptep_set_access_flags(struct mm_struct *mm,
|
||||
pte_t *ptep, pte_t entry)
|
||||
pte_t *ptep, pte_t entry,
|
||||
unsigned long address)
|
||||
{
|
||||
unsigned long set = pte_val(entry) &
|
||||
(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
|
||||
@ -328,15 +336,6 @@ static inline void __ptep_set_access_flags(struct mm_struct *mm,
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 3 })
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { (x).val << 3 })
|
||||
|
||||
#ifndef CONFIG_PPC_4K_PAGES
|
||||
void pgtable_cache_init(void);
|
||||
#else
|
||||
/*
|
||||
* No page table caches to initialise
|
||||
*/
|
||||
#define pgtable_cache_init() do { } while (0)
|
||||
#endif
|
||||
|
||||
extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep,
|
||||
pmd_t **pmdp);
|
||||
|
||||
|
@ -49,6 +49,7 @@
|
||||
#define _PMD_BAD 0x0ff0
|
||||
#define _PMD_PAGE_MASK 0x000c
|
||||
#define _PMD_PAGE_8M 0x000c
|
||||
#define _PMD_PAGE_512K 0x0004
|
||||
|
||||
/* Until my rework is finished, 8xx still needs atomic PTE updates */
|
||||
#define PTE_ATOMIC_UPDATES 1
|
||||
|
@ -27,9 +27,6 @@
|
||||
#define PMD_SIZE (1UL << PMD_SHIFT)
|
||||
#define PMD_MASK (~(PMD_SIZE-1))
|
||||
|
||||
/* With 4k base page size, hugepage PTEs go at the PMD level */
|
||||
#define MIN_HUGEPTE_SHIFT PMD_SHIFT
|
||||
|
||||
/* PUD_SHIFT determines what a third-level page table entry can map */
|
||||
#define PUD_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE)
|
||||
#define PUD_SIZE (1UL << PUD_SHIFT)
|
||||
|
@ -31,9 +31,6 @@
|
||||
#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE)
|
||||
#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE)
|
||||
|
||||
/* With 4k base page size, hugepage PTEs go at the PMD level */
|
||||
#define MIN_HUGEPTE_SHIFT PAGE_SHIFT
|
||||
|
||||
/* PMD_SHIFT determines what a second-level page table entry can map */
|
||||
#define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE)
|
||||
#define PMD_SIZE (1UL << PMD_SHIFT)
|
||||
|
@ -26,15 +26,11 @@
|
||||
#else
|
||||
#define PMD_CACHE_INDEX PMD_INDEX_SIZE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define the address range of the kernel non-linear virtual area
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
#define KERN_VIRT_START ASM_CONST(0x8000000000000000)
|
||||
#else
|
||||
#define KERN_VIRT_START ASM_CONST(0xD000000000000000)
|
||||
#endif
|
||||
#define KERN_VIRT_SIZE ASM_CONST(0x0000100000000000)
|
||||
|
||||
/*
|
||||
@ -43,11 +39,7 @@
|
||||
* (we keep a quarter for the virtual memmap)
|
||||
*/
|
||||
#define VMALLOC_START KERN_VIRT_START
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
#define VMALLOC_SIZE (KERN_VIRT_SIZE >> 2)
|
||||
#else
|
||||
#define VMALLOC_SIZE (KERN_VIRT_SIZE >> 1)
|
||||
#endif
|
||||
#define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE)
|
||||
|
||||
/*
|
||||
@ -85,12 +77,8 @@
|
||||
* Defines the address of the vmemap area, in its own region on
|
||||
* hash table CPUs and after the vmalloc space on Book3E
|
||||
*/
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
#define VMEMMAP_BASE VMALLOC_END
|
||||
#define VMEMMAP_END KERN_IO_START
|
||||
#else
|
||||
#define VMEMMAP_BASE (VMEMMAP_REGION_ID << REGION_SHIFT)
|
||||
#endif
|
||||
#define vmemmap ((struct page *)VMEMMAP_BASE)
|
||||
|
||||
|
||||
@ -301,7 +289,8 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
|
||||
* function doesn't need to flush the hash entry
|
||||
*/
|
||||
static inline void __ptep_set_access_flags(struct mm_struct *mm,
|
||||
pte_t *ptep, pte_t entry)
|
||||
pte_t *ptep, pte_t entry,
|
||||
unsigned long address)
|
||||
{
|
||||
unsigned long bits = pte_val(entry) &
|
||||
(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
|
||||
@ -358,8 +347,6 @@ static inline void __ptep_set_access_flags(struct mm_struct *mm,
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) })
|
||||
#define __swp_entry_to_pte(x) __pte((x).val)
|
||||
|
||||
void pgtable_cache_add(unsigned shift, void (*ctor)(void *));
|
||||
void pgtable_cache_init(void);
|
||||
extern int map_kernel_page(unsigned long ea, unsigned long pa,
|
||||
unsigned long flags);
|
||||
extern int __meminit vmemmap_create_mapping(unsigned long start,
|
||||
|
@ -226,7 +226,11 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
static inline int hugepd_ok(hugepd_t hpd)
|
||||
{
|
||||
#ifdef CONFIG_PPC_8xx
|
||||
return ((hpd.pd & 0x4) != 0);
|
||||
#else
|
||||
return (hpd.pd > 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int pmd_huge(pmd_t pmd)
|
||||
|
@ -78,6 +78,8 @@ static inline pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
|
||||
|
||||
unsigned long vmalloc_to_phys(void *vmalloc_addr);
|
||||
|
||||
void pgtable_cache_add(unsigned shift, void (*ctor)(void *));
|
||||
void pgtable_cache_init(void);
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_PGTABLE_H */
|
||||
|
@ -93,38 +93,6 @@ static inline long register_dtl(unsigned long cpu, unsigned long vpa)
|
||||
return vpa_call(H_VPA_REG_DTL, cpu, vpa);
|
||||
}
|
||||
|
||||
static inline long plpar_page_set_loaned(unsigned long vpa)
|
||||
{
|
||||
unsigned long cmo_page_sz = cmo_get_page_size();
|
||||
long rc = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; !rc && i < PAGE_SIZE; i += cmo_page_sz)
|
||||
rc = plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED, vpa + i, 0);
|
||||
|
||||
for (i -= cmo_page_sz; rc && i != 0; i -= cmo_page_sz)
|
||||
plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE,
|
||||
vpa + i - cmo_page_sz, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline long plpar_page_set_active(unsigned long vpa)
|
||||
{
|
||||
unsigned long cmo_page_sz = cmo_get_page_size();
|
||||
long rc = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; !rc && i < PAGE_SIZE; i += cmo_page_sz)
|
||||
rc = plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE, vpa + i, 0);
|
||||
|
||||
for (i -= cmo_page_sz; rc && i != 0; i -= cmo_page_sz)
|
||||
plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED,
|
||||
vpa + i - cmo_page_sz, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
extern void vpa_init(int cpu);
|
||||
|
||||
static inline long plpar_pte_enter(unsigned long flags,
|
||||
@ -340,4 +308,9 @@ static inline long plapr_set_watchpoint0(unsigned long dawr0, unsigned long dawr
|
||||
return plpar_set_mode(0, H_SET_MODE_RESOURCE_SET_DAWR, dawr0, dawrx0);
|
||||
}
|
||||
|
||||
static inline long plapr_signal_sys_reset(long cpu)
|
||||
{
|
||||
return plpar_hcall_norets(H_SIGNAL_SYS_RESET, cpu);
|
||||
}
|
||||
|
||||
#endif /* _ASM_POWERPC_PLPAR_WRAPPERS_H */
|
||||
|
@ -53,7 +53,7 @@ void eeh_addr_cache_rmv_dev(struct pci_dev *dev);
|
||||
struct eeh_dev *eeh_addr_cache_get_dev(unsigned long addr);
|
||||
void eeh_slot_error_detail(struct eeh_pe *pe, int severity);
|
||||
int eeh_pci_enable(struct eeh_pe *pe, int function);
|
||||
int eeh_reset_pe(struct eeh_pe *);
|
||||
int eeh_pe_reset_full(struct eeh_pe *pe);
|
||||
void eeh_save_bars(struct eeh_dev *edev);
|
||||
int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
|
||||
int rtas_read_config(struct pci_dn *, int where, int size, u32 *val);
|
||||
|
@ -10,9 +10,7 @@
|
||||
#include <asm/ppc-opcode.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#error __FILE__ should only be used in assembler files
|
||||
#else
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
#define SZL (BITS_PER_LONG/8)
|
||||
|
||||
@ -265,10 +263,14 @@ GLUE(.,name):
|
||||
* latter is for those that incdentially must be excluded from probing
|
||||
* and allows them to be linked at more optimal location within text.
|
||||
*/
|
||||
#ifdef CONFIG_KPROBES
|
||||
#define _ASM_NOKPROBE_SYMBOL(entry) \
|
||||
.pushsection "_kprobe_blacklist","aw"; \
|
||||
PPC_LONG (entry) ; \
|
||||
.popsection
|
||||
#else
|
||||
#define _ASM_NOKPROBE_SYMBOL(entry)
|
||||
#endif
|
||||
|
||||
#define FUNC_START(name) _GLOBAL(name)
|
||||
#define FUNC_END(name)
|
||||
@ -779,5 +781,17 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
|
||||
.long 0xa6037b7d; /* mtsrr1 r11 */ \
|
||||
.long 0x2400004c /* rfid */
|
||||
#endif /* !CONFIG_PPC_BOOK3E */
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/*
|
||||
* Helper macro for exception table entries
|
||||
*/
|
||||
#define EX_TABLE(_fault, _target) \
|
||||
stringify_in_c(.section __ex_table,"a";)\
|
||||
stringify_in_c(.balign 4;) \
|
||||
stringify_in_c(.long (_fault) - . ;) \
|
||||
stringify_in_c(.long (_target) - . ;) \
|
||||
stringify_in_c(.previous)
|
||||
|
||||
#endif /* _ASM_POWERPC_PPC_ASM_H */
|
||||
|
@ -312,8 +312,6 @@ struct thread_struct {
|
||||
unsigned long mmcr2;
|
||||
unsigned mmcr0;
|
||||
unsigned used_ebb;
|
||||
unsigned long lmrr;
|
||||
unsigned long lmser;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -159,11 +159,5 @@ struct of_drconf_cell {
|
||||
/* Option Vector 6: IBM PAPR hints */
|
||||
#define OV6_LINUX 0x02 /* Linux is our OS */
|
||||
|
||||
/*
|
||||
* The architecture vector has an array of PVR mask/value pairs,
|
||||
* followed by # option vectors - 1, followed by the option vectors.
|
||||
*/
|
||||
extern unsigned char ibm_architecture_vec[];
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _POWERPC_PROM_H */
|
||||
|
@ -295,8 +295,6 @@
|
||||
#define SPRN_HRMOR 0x139 /* Real mode offset register */
|
||||
#define SPRN_HSRR0 0x13A /* Hypervisor Save/Restore 0 */
|
||||
#define SPRN_HSRR1 0x13B /* Hypervisor Save/Restore 1 */
|
||||
#define SPRN_LMRR 0x32D /* Load Monitor Region Register */
|
||||
#define SPRN_LMSER 0x32E /* Load Monitor Section Enable Register */
|
||||
#define SPRN_ASDR 0x330 /* Access segment descriptor register */
|
||||
#define SPRN_IC 0x350 /* Virtual Instruction Count */
|
||||
#define SPRN_VTB 0x351 /* Virtual Time Base */
|
||||
@ -308,7 +306,6 @@
|
||||
#define SPRN_PMCR 0x374 /* Power Management Control Register */
|
||||
|
||||
/* HFSCR and FSCR bit numbers are the same */
|
||||
#define FSCR_LM_LG 11 /* Enable Load Monitor Registers */
|
||||
#define FSCR_MSGP_LG 10 /* Enable MSGP */
|
||||
#define FSCR_TAR_LG 8 /* Enable Target Address Register */
|
||||
#define FSCR_EBB_LG 7 /* Enable Event Based Branching */
|
||||
@ -319,12 +316,10 @@
|
||||
#define FSCR_VECVSX_LG 1 /* Enable VMX/VSX */
|
||||
#define FSCR_FP_LG 0 /* Enable Floating Point */
|
||||
#define SPRN_FSCR 0x099 /* Facility Status & Control Register */
|
||||
#define FSCR_LM __MASK(FSCR_LM_LG)
|
||||
#define FSCR_TAR __MASK(FSCR_TAR_LG)
|
||||
#define FSCR_EBB __MASK(FSCR_EBB_LG)
|
||||
#define FSCR_DSCR __MASK(FSCR_DSCR_LG)
|
||||
#define SPRN_HFSCR 0xbe /* HV=1 Facility Status & Control Register */
|
||||
#define HFSCR_LM __MASK(FSCR_LM_LG)
|
||||
#define HFSCR_MSGP __MASK(FSCR_MSGP_LG)
|
||||
#define HFSCR_TAR __MASK(FSCR_TAR_LG)
|
||||
#define HFSCR_EBB __MASK(FSCR_EBB_LG)
|
||||
|
@ -4,7 +4,7 @@
|
||||
#ifndef _ASM_POWERPC_REG_8xx_H
|
||||
#define _ASM_POWERPC_REG_8xx_H
|
||||
|
||||
#include <asm/mmu-8xx.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
/* Cache control on the MPC8xx is provided through some additional
|
||||
* special purpose registers.
|
||||
|
@ -176,7 +176,7 @@ static inline void set_hard_smp_processor_id(int cpu, int phys)
|
||||
#endif /* !CONFIG_SMP */
|
||||
#endif /* !CONFIG_PPC64 */
|
||||
|
||||
#if defined(CONFIG_PPC64) && (defined(CONFIG_SMP) || defined(CONFIG_KEXEC))
|
||||
#if defined(CONFIG_PPC64) && (defined(CONFIG_SMP) || defined(CONFIG_KEXEC_CORE))
|
||||
extern void smp_release_cpus(void);
|
||||
#else
|
||||
static inline void smp_release_cpus(void) { };
|
||||
|
40
arch/powerpc/include/asm/stackprotector.h
Normal file
40
arch/powerpc/include/asm/stackprotector.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* GCC stack protector support.
|
||||
*
|
||||
* Stack protector works by putting predefined pattern at the start of
|
||||
* the stack frame and verifying that it hasn't been overwritten when
|
||||
* returning from the function. The pattern is called stack canary
|
||||
* and gcc expects it to be defined by a global variable called
|
||||
* "__stack_chk_guard" on PPC. This unfortunately means that on SMP
|
||||
* we cannot have a different canary value per task.
|
||||
*/
|
||||
|
||||
#ifndef _ASM_STACKPROTECTOR_H
|
||||
#define _ASM_STACKPROTECTOR_H
|
||||
|
||||
#include <linux/random.h>
|
||||
#include <linux/version.h>
|
||||
#include <asm/reg.h>
|
||||
|
||||
extern unsigned long __stack_chk_guard;
|
||||
|
||||
/*
|
||||
* Initialize the stackprotector canary value.
|
||||
*
|
||||
* NOTE: this must only be called from functions that never return,
|
||||
* and it must always be inlined.
|
||||
*/
|
||||
static __always_inline void boot_init_stack_canary(void)
|
||||
{
|
||||
unsigned long canary;
|
||||
|
||||
/* Try to get a semi random initial value. */
|
||||
get_random_bytes(&canary, sizeof(canary));
|
||||
canary ^= mftb();
|
||||
canary ^= LINUX_VERSION_CODE;
|
||||
|
||||
current->stack_canary = canary;
|
||||
__stack_chk_guard = current->stack_canary;
|
||||
}
|
||||
|
||||
#endif /* _ASM_STACKPROTECTOR_H */
|
@ -386,3 +386,4 @@ SYSCALL(mlock2)
|
||||
SYSCALL(copy_file_range)
|
||||
COMPAT_SYS_SPU(preadv2)
|
||||
COMPAT_SYS_SPU(pwritev2)
|
||||
SYSCALL(kexec_file_load)
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/asm-compat.h>
|
||||
#include <asm/ppc_asm.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
@ -63,23 +64,30 @@
|
||||
__access_ok((__force unsigned long)(addr), (size), get_fs()))
|
||||
|
||||
/*
|
||||
* The exception table consists of pairs of addresses: the first is the
|
||||
* address of an instruction that is allowed to fault, and the second is
|
||||
* The exception table consists of pairs of relative addresses: the first is
|
||||
* the address of an instruction that is allowed to fault, and the second is
|
||||
* the address at which the program should continue. No registers are
|
||||
* modified, so it is entirely up to the continuation code to figure out
|
||||
* what to do.
|
||||
* modified, so it is entirely up to the continuation code to figure out what
|
||||
* to do.
|
||||
*
|
||||
* All the routines below use bits of fixup code that are out of line
|
||||
* with the main instruction path. This means when everything is well,
|
||||
* we don't even have to jump over them. Further, they do not intrude
|
||||
* on our cache or tlb entries.
|
||||
* All the routines below use bits of fixup code that are out of line with the
|
||||
* main instruction path. This means when everything is well, we don't even
|
||||
* have to jump over them. Further, they do not intrude on our cache or tlb
|
||||
* entries.
|
||||
*/
|
||||
|
||||
#define ARCH_HAS_RELATIVE_EXTABLE
|
||||
|
||||
struct exception_table_entry {
|
||||
unsigned long insn;
|
||||
unsigned long fixup;
|
||||
int insn;
|
||||
int fixup;
|
||||
};
|
||||
|
||||
static inline unsigned long extable_fixup(const struct exception_table_entry *x)
|
||||
{
|
||||
return (unsigned long)&x->fixup + x->fixup;
|
||||
}
|
||||
|
||||
/*
|
||||
* These are the main single-value transfer routines. They automatically
|
||||
* use the right size if we just have the right pointer type.
|
||||
@ -132,10 +140,7 @@ extern long __put_user_bad(void);
|
||||
"3: li %0,%3\n" \
|
||||
" b 2b\n" \
|
||||
".previous\n" \
|
||||
".section __ex_table,\"a\"\n" \
|
||||
PPC_LONG_ALIGN "\n" \
|
||||
PPC_LONG "1b,3b\n" \
|
||||
".previous" \
|
||||
EX_TABLE(1b, 3b) \
|
||||
: "=r" (err) \
|
||||
: "r" (x), "b" (addr), "i" (-EFAULT), "0" (err))
|
||||
|
||||
@ -152,11 +157,8 @@ extern long __put_user_bad(void);
|
||||
"4: li %0,%3\n" \
|
||||
" b 3b\n" \
|
||||
".previous\n" \
|
||||
".section __ex_table,\"a\"\n" \
|
||||
PPC_LONG_ALIGN "\n" \
|
||||
PPC_LONG "1b,4b\n" \
|
||||
PPC_LONG "2b,4b\n" \
|
||||
".previous" \
|
||||
EX_TABLE(1b, 4b) \
|
||||
EX_TABLE(2b, 4b) \
|
||||
: "=r" (err) \
|
||||
: "r" (x), "b" (addr), "i" (-EFAULT), "0" (err))
|
||||
#endif /* __powerpc64__ */
|
||||
@ -215,10 +217,7 @@ extern long __get_user_bad(void);
|
||||
" li %1,0\n" \
|
||||
" b 2b\n" \
|
||||
".previous\n" \
|
||||
".section __ex_table,\"a\"\n" \
|
||||
PPC_LONG_ALIGN "\n" \
|
||||
PPC_LONG "1b,3b\n" \
|
||||
".previous" \
|
||||
EX_TABLE(1b, 3b) \
|
||||
: "=r" (err), "=r" (x) \
|
||||
: "b" (addr), "i" (-EFAULT), "0" (err))
|
||||
|
||||
@ -237,11 +236,8 @@ extern long __get_user_bad(void);
|
||||
" li %1+1,0\n" \
|
||||
" b 3b\n" \
|
||||
".previous\n" \
|
||||
".section __ex_table,\"a\"\n" \
|
||||
PPC_LONG_ALIGN "\n" \
|
||||
PPC_LONG "1b,4b\n" \
|
||||
PPC_LONG "2b,4b\n" \
|
||||
".previous" \
|
||||
EX_TABLE(1b, 4b) \
|
||||
EX_TABLE(2b, 4b) \
|
||||
: "=r" (err), "=&r" (x) \
|
||||
: "b" (addr), "i" (-EFAULT), "0" (err))
|
||||
#endif /* __powerpc64__ */
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <uapi/asm/unistd.h>
|
||||
|
||||
|
||||
#define NR_syscalls 382
|
||||
#define NR_syscalls 383
|
||||
|
||||
#define __NR__exit __NR_exit
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/asm-compat.h>
|
||||
#include <asm/ppc_asm.h>
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
|
||||
@ -193,10 +194,7 @@ static inline unsigned long load_unaligned_zeropad(const void *addr)
|
||||
#endif
|
||||
"b 2b\n"
|
||||
".previous\n"
|
||||
".section __ex_table,\"a\"\n\t"
|
||||
PPC_LONG_ALIGN "\n\t"
|
||||
PPC_LONG "1b,3b\n"
|
||||
".previous"
|
||||
EX_TABLE(1b, 3b)
|
||||
: [tmp] "=&b" (tmp), [offset] "=&r" (offset), [ret] "=&r" (ret)
|
||||
: [addr] "b" (addr), "m" (*(unsigned long *)addr));
|
||||
|
||||
|
@ -392,5 +392,6 @@
|
||||
#define __NR_copy_file_range 379
|
||||
#define __NR_preadv2 380
|
||||
#define __NR_pwritev2 381
|
||||
#define __NR_kexec_file_load 382
|
||||
|
||||
#endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
|
||||
|
@ -19,6 +19,10 @@ CFLAGS_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
|
||||
CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
|
||||
CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
|
||||
|
||||
# -fstack-protector triggers protection checks in this code,
|
||||
# but it is being used too early to link to meaningful stack_chk logic.
|
||||
CFLAGS_prom_init.o += $(call cc-option, -fno-stack-protector)
|
||||
|
||||
ifdef CONFIG_FUNCTION_TRACER
|
||||
# Do not trace early boot code
|
||||
CFLAGS_REMOVE_cputable.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
|
||||
@ -58,8 +62,6 @@ 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_IBMVIO) += vio.o
|
||||
obj-$(CONFIG_IBMEBUS) += ibmebus.o
|
||||
obj-$(CONFIG_EEH) += eeh.o eeh_pe.o eeh_dev.o eeh_cache.o \
|
||||
eeh_driver.o eeh_event.o eeh_sysfs.o
|
||||
obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
|
||||
@ -107,8 +109,9 @@ pci64-$(CONFIG_PPC64) += pci_dn.o pci-hotplug.o isa-bridge.o
|
||||
obj-$(CONFIG_PCI) += pci_$(BITS).o $(pci64-y) \
|
||||
pci-common.o pci_of_scan.o
|
||||
obj-$(CONFIG_PCI_MSI) += msi.o
|
||||
obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o \
|
||||
obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o crash.o \
|
||||
machine_kexec_$(BITS).o
|
||||
obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file_$(BITS).o kexec_elf_$(BITS).o
|
||||
obj-$(CONFIG_AUDIT) += audit.o
|
||||
obj64-$(CONFIG_AUDIT) += compat_audit.o
|
||||
|
||||
@ -128,7 +131,7 @@ obj64-$(CONFIG_PPC_TRANSACTIONAL_MEM) += tm.o
|
||||
obj-$(CONFIG_PPC64) += $(obj64-y)
|
||||
obj-$(CONFIG_PPC32) += $(obj32-y)
|
||||
|
||||
ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
|
||||
ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC_CORE),)
|
||||
obj-y += ppc_save_regs.o
|
||||
endif
|
||||
|
||||
|
@ -91,6 +91,9 @@ int main(void)
|
||||
DEFINE(TI_livepatch_sp, offsetof(struct thread_info, livepatch_sp));
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CC_STACKPROTECTOR
|
||||
DEFINE(TSK_STACK_CANARY, offsetof(struct task_struct, stack_canary));
|
||||
#endif
|
||||
DEFINE(KSP, offsetof(struct thread_struct, ksp));
|
||||
DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
|
||||
#ifdef CONFIG_BOOKE
|
||||
|
@ -96,6 +96,7 @@ _GLOBAL(__setup_cpu_power9)
|
||||
mtlr r11
|
||||
beqlr
|
||||
li r0,0
|
||||
mtspr SPRN_PSSCR,r0
|
||||
mtspr SPRN_LPID,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE)
|
||||
@ -116,6 +117,7 @@ _GLOBAL(__restore_cpu_power9)
|
||||
mtlr r11
|
||||
beqlr
|
||||
li r0,0
|
||||
mtspr SPRN_PSSCR,r0
|
||||
mtspr SPRN_LPID,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE)
|
||||
|
@ -372,7 +372,7 @@ static int eeh_phb_check_failure(struct eeh_pe *pe)
|
||||
/* Find the PHB PE */
|
||||
phb_pe = eeh_phb_pe_get(pe->phb);
|
||||
if (!phb_pe) {
|
||||
pr_warn("%s Can't find PE for PHB#%d\n",
|
||||
pr_warn("%s Can't find PE for PHB#%x\n",
|
||||
__func__, pe->phb->global_number);
|
||||
return -EEXIST;
|
||||
}
|
||||
@ -664,7 +664,7 @@ int eeh_pci_enable(struct eeh_pe *pe, int function)
|
||||
rc = eeh_ops->set_option(pe, function);
|
||||
if (rc)
|
||||
pr_warn("%s: Unexpected state change %d on "
|
||||
"PHB#%d-PE#%x, err=%d\n",
|
||||
"PHB#%x-PE#%x, err=%d\n",
|
||||
__func__, function, pe->phb->global_number,
|
||||
pe->addr, rc);
|
||||
|
||||
@ -808,76 +808,67 @@ static void *eeh_set_dev_freset(void *data, void *flag)
|
||||
}
|
||||
|
||||
/**
|
||||
* eeh_reset_pe_once - Assert the pci #RST line for 1/4 second
|
||||
* eeh_pe_reset_full - Complete a full reset process on the indicated PE
|
||||
* @pe: EEH PE
|
||||
*
|
||||
* Assert the PCI #RST line for 1/4 second.
|
||||
* This function executes a full reset procedure on a PE, including setting
|
||||
* the appropriate flags, performing a fundamental or hot reset, and then
|
||||
* deactivating the reset status. It is designed to be used within the EEH
|
||||
* subsystem, as opposed to eeh_pe_reset which is exported to drivers and
|
||||
* only performs a single operation at a time.
|
||||
*
|
||||
* This function will attempt to reset a PE three times before failing.
|
||||
*/
|
||||
static void eeh_reset_pe_once(struct eeh_pe *pe)
|
||||
int eeh_pe_reset_full(struct eeh_pe *pe)
|
||||
{
|
||||
int active_flags = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE);
|
||||
int reset_state = (EEH_PE_RESET | EEH_PE_CFG_BLOCKED);
|
||||
int type = EEH_RESET_HOT;
|
||||
unsigned int freset = 0;
|
||||
int i, state, ret;
|
||||
|
||||
/* Determine type of EEH reset required for
|
||||
* Partitionable Endpoint, a hot-reset (1)
|
||||
* or a fundamental reset (3).
|
||||
* A fundamental reset required by any device under
|
||||
* Partitionable Endpoint trumps hot-reset.
|
||||
/*
|
||||
* Determine the type of reset to perform - hot or fundamental.
|
||||
* Hot reset is the default operation, unless any device under the
|
||||
* PE requires a fundamental reset.
|
||||
*/
|
||||
eeh_pe_dev_traverse(pe, eeh_set_dev_freset, &freset);
|
||||
|
||||
if (freset)
|
||||
eeh_ops->reset(pe, EEH_RESET_FUNDAMENTAL);
|
||||
else
|
||||
eeh_ops->reset(pe, EEH_RESET_HOT);
|
||||
type = EEH_RESET_FUNDAMENTAL;
|
||||
|
||||
eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
|
||||
}
|
||||
/* Mark the PE as in reset state and block config space accesses */
|
||||
eeh_pe_state_mark(pe, reset_state);
|
||||
|
||||
/**
|
||||
* eeh_reset_pe - Reset the indicated PE
|
||||
* @pe: EEH PE
|
||||
*
|
||||
* This routine should be called to reset indicated device, including
|
||||
* PE. A PE might include multiple PCI devices and sometimes PCI bridges
|
||||
* might be involved as well.
|
||||
*/
|
||||
int eeh_reset_pe(struct eeh_pe *pe)
|
||||
{
|
||||
int flags = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE);
|
||||
int i, state, ret;
|
||||
|
||||
/* Mark as reset and block config space */
|
||||
eeh_pe_state_mark(pe, EEH_PE_RESET | EEH_PE_CFG_BLOCKED);
|
||||
|
||||
/* Take three shots at resetting the bus */
|
||||
/* Make three attempts at resetting the bus */
|
||||
for (i = 0; i < 3; i++) {
|
||||
eeh_reset_pe_once(pe);
|
||||
ret = eeh_pe_reset(pe, type);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
/*
|
||||
* EEH_PE_ISOLATED is expected to be removed after
|
||||
* BAR restore.
|
||||
*/
|
||||
ret = eeh_pe_reset(pe, EEH_RESET_DEACTIVATE);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
/* Wait until the PE is in a functioning state */
|
||||
state = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
|
||||
if ((state & flags) == flags) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
if ((state & active_flags) == active_flags)
|
||||
break;
|
||||
|
||||
if (state < 0) {
|
||||
pr_warn("%s: Unrecoverable slot failure on PHB#%d-PE#%x",
|
||||
pr_warn("%s: Unrecoverable slot failure on PHB#%x-PE#%x",
|
||||
__func__, pe->phb->global_number, pe->addr);
|
||||
ret = -ENOTRECOVERABLE;
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We might run out of credits */
|
||||
/* Set error in case this is our last attempt */
|
||||
ret = -EIO;
|
||||
pr_warn("%s: Failure %d resetting PHB#%x-PE#%x\n (%d)\n",
|
||||
__func__, state, pe->phb->global_number, pe->addr, (i + 1));
|
||||
}
|
||||
|
||||
out:
|
||||
eeh_pe_state_clear(pe, EEH_PE_RESET | EEH_PE_CFG_BLOCKED);
|
||||
eeh_pe_state_clear(pe, reset_state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1601,6 +1592,7 @@ static int eeh_pe_reenable_devices(struct eeh_pe *pe)
|
||||
return eeh_unfreeze_pe(pe, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* eeh_pe_reset - Issue PE reset according to specified type
|
||||
* @pe: EEH PE
|
||||
|
@ -588,7 +588,7 @@ int eeh_pe_reset_and_recover(struct eeh_pe *pe)
|
||||
eeh_pe_dev_traverse(pe, eeh_dev_save_state, NULL);
|
||||
|
||||
/* Issue reset */
|
||||
ret = eeh_reset_pe(pe);
|
||||
ret = eeh_pe_reset_full(pe);
|
||||
if (ret) {
|
||||
eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
|
||||
return ret;
|
||||
@ -659,7 +659,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus,
|
||||
* config accesses. So we prefer to block them. However, controlled
|
||||
* PCI config accesses initiated from EEH itself are allowed.
|
||||
*/
|
||||
rc = eeh_reset_pe(pe);
|
||||
rc = eeh_pe_reset_full(pe);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -734,7 +734,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
|
||||
|
||||
frozen_bus = eeh_pe_bus_get(pe);
|
||||
if (!frozen_bus) {
|
||||
pr_err("%s: Cannot find PCI bus for PHB#%d-PE#%x\n",
|
||||
pr_err("%s: Cannot find PCI bus for PHB#%x-PE#%x\n",
|
||||
__func__, pe->phb->global_number, pe->addr);
|
||||
return;
|
||||
}
|
||||
@ -878,7 +878,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
|
||||
* are due to poorly seated PCI cards. Only 10% or so are
|
||||
* due to actual, failed cards.
|
||||
*/
|
||||
pr_err("EEH: PHB#%d-PE#%x has failed %d times in the\n"
|
||||
pr_err("EEH: PHB#%x-PE#%x has failed %d times in the\n"
|
||||
"last hour and has been permanently disabled.\n"
|
||||
"Please try reseating or replacing it.\n",
|
||||
pe->phb->global_number, pe->addr,
|
||||
@ -886,7 +886,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
|
||||
goto perm_error;
|
||||
|
||||
hard_fail:
|
||||
pr_err("EEH: Unable to recover from failure from PHB#%d-PE#%x.\n"
|
||||
pr_err("EEH: Unable to recover from failure from PHB#%x-PE#%x.\n"
|
||||
"Please try reseating or replacing it\n",
|
||||
pe->phb->global_number, pe->addr);
|
||||
|
||||
@ -1000,7 +1000,7 @@ static void eeh_handle_special_event(void)
|
||||
bus = eeh_pe_bus_get(phb_pe);
|
||||
if (!bus) {
|
||||
pr_err("%s: Cannot find PCI bus for "
|
||||
"PHB#%d-PE#%x\n",
|
||||
"PHB#%x-PE#%x\n",
|
||||
__func__,
|
||||
pe->phb->global_number,
|
||||
pe->addr);
|
||||
|
@ -75,11 +75,11 @@ static int eeh_event_handler(void * dummy)
|
||||
if (pe) {
|
||||
eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
|
||||
if (pe->type & EEH_PE_PHB)
|
||||
pr_info("EEH: Detected error on PHB#%d\n",
|
||||
pr_info("EEH: Detected error on PHB#%x\n",
|
||||
pe->phb->global_number);
|
||||
else
|
||||
pr_info("EEH: Detected PCI bus error on "
|
||||
"PHB#%d-PE#%x\n",
|
||||
"PHB#%x-PE#%x\n",
|
||||
pe->phb->global_number, pe->addr);
|
||||
eeh_handle_event(pe);
|
||||
eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
|
||||
|
@ -104,7 +104,7 @@ int eeh_phb_pe_create(struct pci_controller *phb)
|
||||
/* Put it into the list */
|
||||
list_add_tail(&pe->child, &eeh_phb_pe);
|
||||
|
||||
pr_debug("EEH: Add PE for PHB#%d\n", phb->global_number);
|
||||
pr_debug("EEH: Add PE for PHB#%x\n", phb->global_number);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -333,7 +333,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
|
||||
|
||||
/* Check if the PE number is valid */
|
||||
if (!eeh_has_flag(EEH_VALID_PE_ZERO) && !edev->pe_config_addr) {
|
||||
pr_err("%s: Invalid PE#0 for edev 0x%x on PHB#%d\n",
|
||||
pr_err("%s: Invalid PE#0 for edev 0x%x on PHB#%x\n",
|
||||
__func__, edev->config_addr, edev->phb->global_number);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -674,7 +674,11 @@ BEGIN_FTR_SECTION
|
||||
mtspr SPRN_SPEFSCR,r0 /* restore SPEFSCR reg */
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_SPE)
|
||||
#endif /* CONFIG_SPE */
|
||||
|
||||
#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
|
||||
lwz r0,TSK_STACK_CANARY(r2)
|
||||
lis r4,__stack_chk_guard@ha
|
||||
stw r0,__stack_chk_guard@l(r4)
|
||||
#endif
|
||||
lwz r0,_CCR(r1)
|
||||
mtcrf 0xFF,r0
|
||||
/* r3-r12 are destroyed -- Cort */
|
||||
|
@ -923,10 +923,10 @@ kernel_dbg_exc:
|
||||
PROLOG_ADDITION_NONE)
|
||||
EXCEPTION_COMMON(0x340)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
INTS_RESTORE_HARD
|
||||
bl .unknown_exception
|
||||
b .ret_from_except
|
||||
bl unknown_exception
|
||||
b ret_from_except
|
||||
|
||||
/*
|
||||
* An interrupt came in while soft-disabled; We mark paca->irq_happened
|
||||
|
@ -1408,7 +1408,7 @@ USE_TEXT_SECTION()
|
||||
/*
|
||||
* Hash table stuff
|
||||
*/
|
||||
.align 7
|
||||
.balign IFETCH_ALIGN_BYTES
|
||||
do_hash_page:
|
||||
#ifdef CONFIG_PPC_STD_MMU_64
|
||||
andis. r0,r4,0xa410 /* weird error? */
|
||||
|
@ -47,13 +47,11 @@ ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
|
||||
unsigned int replaced;
|
||||
|
||||
/*
|
||||
* Note: Due to modules and __init, code can
|
||||
* disappear and change, we need to protect against faulting
|
||||
* as well as code changing. We do this by using the
|
||||
* probe_kernel_* functions.
|
||||
*
|
||||
* No real locking needed, this code is run through
|
||||
* kstop_machine, or before SMP starts.
|
||||
* Note:
|
||||
* We are paranoid about modifying text, as if a bug was to happen, it
|
||||
* could cause us to read or write to someplace that could cause harm.
|
||||
* Carefully read and modify the code with probe_kernel_*(), and make
|
||||
* sure what we read is what we expected it to be before modifying it.
|
||||
*/
|
||||
|
||||
/* read the text we want to modify */
|
||||
|
@ -107,12 +107,19 @@ __secondary_hold_acknowledge:
|
||||
* crash_kernel region. The loader is responsible for
|
||||
* observing the alignment requirement.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_RELOCATABLE_TEST
|
||||
#define RUN_AT_LOAD_DEFAULT 1 /* Test relocation, do not copy to 0 */
|
||||
#else
|
||||
#define RUN_AT_LOAD_DEFAULT 0x72756e30 /* "run0" -- relocate to 0 by default */
|
||||
#endif
|
||||
|
||||
/* Do not move this variable as kexec-tools knows about it. */
|
||||
. = 0x5c
|
||||
.globl __run_at_load
|
||||
__run_at_load:
|
||||
DEFINE_FIXED_SYMBOL(__run_at_load)
|
||||
.long 0x72756e30 /* "run0" -- relocate to 0 by default */
|
||||
.long RUN_AT_LOAD_DEFAULT
|
||||
#endif
|
||||
|
||||
. = 0x60
|
||||
@ -153,7 +160,7 @@ __secondary_hold:
|
||||
cmpdi 0,r12,0
|
||||
beq 100b
|
||||
|
||||
#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
|
||||
#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC_CORE)
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
tovirt(r12,r12)
|
||||
#endif
|
||||
@ -214,9 +221,9 @@ booting_thread_hwid:
|
||||
*/
|
||||
_GLOBAL(book3e_start_thread)
|
||||
LOAD_REG_IMMEDIATE(r5, MSR_KERNEL)
|
||||
cmpi 0, r3, 0
|
||||
cmpwi r3, 0
|
||||
beq 10f
|
||||
cmpi 0, r3, 1
|
||||
cmpwi r3, 1
|
||||
beq 11f
|
||||
/* If the thread id is invalid, just exit. */
|
||||
b 13f
|
||||
@ -241,9 +248,9 @@ _GLOBAL(book3e_start_thread)
|
||||
* r3 = the thread physical id
|
||||
*/
|
||||
_GLOBAL(book3e_stop_thread)
|
||||
cmpi 0, r3, 0
|
||||
cmpwi r3, 0
|
||||
beq 10f
|
||||
cmpi 0, r3, 1
|
||||
cmpwi r3, 1
|
||||
beq 10f
|
||||
/* If the thread id is invalid, just exit. */
|
||||
b 13f
|
||||
|
@ -73,6 +73,9 @@
|
||||
#define RPN_PATTERN 0x00f0
|
||||
#endif
|
||||
|
||||
#define PAGE_SHIFT_512K 19
|
||||
#define PAGE_SHIFT_8M 23
|
||||
|
||||
__HEAD
|
||||
_ENTRY(_stext);
|
||||
_ENTRY(_start);
|
||||
@ -322,7 +325,7 @@ SystemCall:
|
||||
#endif
|
||||
|
||||
InstructionTLBMiss:
|
||||
#if defined(CONFIG_8xx_CPU6) || defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC)
|
||||
#if defined(CONFIG_8xx_CPU6) || defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC) || defined (CONFIG_HUGETLB_PAGE)
|
||||
mtspr SPRN_SPRG_SCRATCH2, r3
|
||||
#endif
|
||||
EXCEPTION_PROLOG_0
|
||||
@ -332,10 +335,12 @@ InstructionTLBMiss:
|
||||
*/
|
||||
mfspr r10, SPRN_SRR0 /* Get effective address of fault */
|
||||
INVALIDATE_ADJACENT_PAGES_CPU15(r11, r10)
|
||||
#if defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC)
|
||||
/* Only modules will cause ITLB Misses as we always
|
||||
* pin the first 8MB of kernel memory */
|
||||
#if defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC) || defined (CONFIG_HUGETLB_PAGE)
|
||||
mfcr r3
|
||||
#endif
|
||||
#if defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC)
|
||||
IS_KERNEL(r11, r10)
|
||||
#endif
|
||||
mfspr r11, SPRN_M_TW /* Get level 1 table */
|
||||
@ -343,7 +348,6 @@ InstructionTLBMiss:
|
||||
BRANCH_UNLESS_KERNEL(3f)
|
||||
lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha
|
||||
3:
|
||||
mtcr r3
|
||||
#endif
|
||||
/* Insert level 1 index */
|
||||
rlwimi r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29
|
||||
@ -351,14 +355,25 @@ InstructionTLBMiss:
|
||||
|
||||
/* Extract level 2 index */
|
||||
rlwinm r10, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
mtcr r11
|
||||
bt- 28, 10f /* bit 28 = Large page (8M) */
|
||||
bt- 29, 20f /* bit 29 = Large page (8M or 512k) */
|
||||
#endif
|
||||
rlwimi r10, r11, 0, 0, 32 - PAGE_SHIFT - 1 /* Add level 2 base */
|
||||
lwz r10, 0(r10) /* Get the pte */
|
||||
|
||||
4:
|
||||
#if defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC) || defined (CONFIG_HUGETLB_PAGE)
|
||||
mtcr r3
|
||||
#endif
|
||||
/* Insert the APG into the TWC from the Linux PTE. */
|
||||
rlwimi r11, r10, 0, 25, 26
|
||||
/* Load the MI_TWC with the attributes for this "segment." */
|
||||
MTSPR_CPU6(SPRN_MI_TWC, r11, r3) /* Set segment attributes */
|
||||
|
||||
#if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
|
||||
rlwimi r10, r11, 1, MI_SPS16K
|
||||
#endif
|
||||
#ifdef CONFIG_SWAP
|
||||
rlwinm r11, r10, 32-5, _PAGE_PRESENT
|
||||
and r11, r11, r10
|
||||
@ -371,16 +386,45 @@ InstructionTLBMiss:
|
||||
* set. All other Linux PTE bits control the behavior
|
||||
* of the MMU.
|
||||
*/
|
||||
#if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
|
||||
rlwimi r10, r11, 0, 0x0ff0 /* Set 24-27, clear 20-23 */
|
||||
#else
|
||||
rlwimi r10, r11, 0, 0x0ff8 /* Set 24-27, clear 20-23,28 */
|
||||
#endif
|
||||
MTSPR_CPU6(SPRN_MI_RPN, r10, r3) /* Update TLB entry */
|
||||
|
||||
/* Restore registers */
|
||||
#if defined(CONFIG_8xx_CPU6) || defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC)
|
||||
#if defined(CONFIG_8xx_CPU6) || defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC) || defined (CONFIG_HUGETLB_PAGE)
|
||||
mfspr r3, SPRN_SPRG_SCRATCH2
|
||||
#endif
|
||||
EXCEPTION_EPILOG_0
|
||||
rfi
|
||||
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
10: /* 8M pages */
|
||||
#ifdef CONFIG_PPC_16K_PAGES
|
||||
/* Extract level 2 index */
|
||||
rlwinm r10, r10, 32 - (PAGE_SHIFT_8M - PAGE_SHIFT), 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1), 29
|
||||
/* Add level 2 base */
|
||||
rlwimi r10, r11, 0, 0, 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1) - 1
|
||||
#else
|
||||
/* Level 2 base */
|
||||
rlwinm r10, r11, 0, ~HUGEPD_SHIFT_MASK
|
||||
#endif
|
||||
lwz r10, 0(r10) /* Get the pte */
|
||||
rlwinm r11, r11, 0, 0xf
|
||||
b 4b
|
||||
|
||||
20: /* 512k pages */
|
||||
/* Extract level 2 index */
|
||||
rlwinm r10, r10, 32 - (PAGE_SHIFT_512K - PAGE_SHIFT), 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1), 29
|
||||
/* Add level 2 base */
|
||||
rlwimi r10, r11, 0, 0, 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1) - 1
|
||||
lwz r10, 0(r10) /* Get the pte */
|
||||
rlwinm r11, r11, 0, 0xf
|
||||
b 4b
|
||||
#endif
|
||||
|
||||
. = 0x1200
|
||||
DataStoreTLBMiss:
|
||||
mtspr SPRN_SPRG_SCRATCH2, r3
|
||||
@ -407,7 +451,6 @@ _ENTRY(DTLBMiss_jmp)
|
||||
#endif
|
||||
blt cr7, DTLBMissLinear
|
||||
3:
|
||||
mtcr r3
|
||||
mfspr r10, SPRN_MD_EPN
|
||||
|
||||
/* Insert level 1 index */
|
||||
@ -418,8 +461,15 @@ _ENTRY(DTLBMiss_jmp)
|
||||
*/
|
||||
/* Extract level 2 index */
|
||||
rlwinm r10, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
mtcr r11
|
||||
bt- 28, 10f /* bit 28 = Large page (8M) */
|
||||
bt- 29, 20f /* bit 29 = Large page (8M or 512k) */
|
||||
#endif
|
||||
rlwimi r10, r11, 0, 0, 32 - PAGE_SHIFT - 1 /* Add level 2 base */
|
||||
lwz r10, 0(r10) /* Get the pte */
|
||||
4:
|
||||
mtcr r3
|
||||
|
||||
/* Insert the Guarded flag and APG into the TWC from the Linux PTE.
|
||||
* It is bit 26-27 of both the Linux PTE and the TWC (at least
|
||||
@ -434,6 +484,11 @@ _ENTRY(DTLBMiss_jmp)
|
||||
rlwimi r11, r10, 32-5, 30, 30
|
||||
MTSPR_CPU6(SPRN_MD_TWC, r11, r3)
|
||||
|
||||
/* In 4k pages mode, SPS (bit 28) in RPN must match PS[1] (bit 29)
|
||||
* In 16k pages mode, SPS is always 1 */
|
||||
#if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
|
||||
rlwimi r10, r11, 1, MD_SPS16K
|
||||
#endif
|
||||
/* 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
|
||||
@ -455,7 +510,11 @@ _ENTRY(DTLBMiss_jmp)
|
||||
* of the MMU.
|
||||
*/
|
||||
li r11, RPN_PATTERN
|
||||
#if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
|
||||
rlwimi r10, r11, 0, 24, 27 /* Set 24-27 */
|
||||
#else
|
||||
rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
|
||||
#endif
|
||||
rlwimi r10, r11, 0, 20, 20 /* clear 20 */
|
||||
MTSPR_CPU6(SPRN_MD_RPN, r10, r3) /* Update TLB entry */
|
||||
|
||||
@ -465,6 +524,30 @@ _ENTRY(DTLBMiss_jmp)
|
||||
EXCEPTION_EPILOG_0
|
||||
rfi
|
||||
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
10: /* 8M pages */
|
||||
/* Extract level 2 index */
|
||||
#ifdef CONFIG_PPC_16K_PAGES
|
||||
rlwinm r10, r10, 32 - (PAGE_SHIFT_8M - PAGE_SHIFT), 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1), 29
|
||||
/* Add level 2 base */
|
||||
rlwimi r10, r11, 0, 0, 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1) - 1
|
||||
#else
|
||||
/* Level 2 base */
|
||||
rlwinm r10, r11, 0, ~HUGEPD_SHIFT_MASK
|
||||
#endif
|
||||
lwz r10, 0(r10) /* Get the pte */
|
||||
rlwinm r11, r11, 0, 0xf
|
||||
b 4b
|
||||
|
||||
20: /* 512k pages */
|
||||
/* Extract level 2 index */
|
||||
rlwinm r10, r10, 32 - (PAGE_SHIFT_512K - PAGE_SHIFT), 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1), 29
|
||||
/* Add level 2 base */
|
||||
rlwimi r10, r11, 0, 0, 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1) - 1
|
||||
lwz r10, 0(r10) /* Get the pte */
|
||||
rlwinm r11, r11, 0, 0xf
|
||||
b 4b
|
||||
#endif
|
||||
|
||||
/* This is an instruction TLB error on the MPC8xx. This could be due
|
||||
* to many reasons, such as executing guarded memory or illegal instruction
|
||||
@ -586,6 +669,9 @@ _ENTRY(FixupDAR_cmp)
|
||||
/* Insert level 1 index */
|
||||
3: rlwimi r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29
|
||||
lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11) /* Get the level 1 entry */
|
||||
mtcr r11
|
||||
bt 28,200f /* bit 28 = Large page (8M) */
|
||||
bt 29,202f /* bit 29 = Large page (8M or 512K) */
|
||||
rlwinm r11, r11,0,0,19 /* Extract page descriptor page address */
|
||||
/* Insert level 2 index */
|
||||
rlwimi r11, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
|
||||
@ -611,6 +697,27 @@ _ENTRY(FixupDAR_cmp)
|
||||
141: mfspr r10,SPRN_SPRG_SCRATCH2
|
||||
b DARFixed /* Nope, go back to normal TLB processing */
|
||||
|
||||
/* concat physical page address(r11) and page offset(r10) */
|
||||
200:
|
||||
#ifdef CONFIG_PPC_16K_PAGES
|
||||
rlwinm r11, r11, 0, 0, 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1) - 1
|
||||
rlwimi r11, r10, 32 - (PAGE_SHIFT_8M - 2), 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1), 29
|
||||
#else
|
||||
rlwinm r11, r10, 0, ~HUGEPD_SHIFT_MASK
|
||||
#endif
|
||||
lwz r11, 0(r11) /* Get the pte */
|
||||
/* concat physical page address(r11) and page offset(r10) */
|
||||
rlwimi r11, r10, 0, 32 - PAGE_SHIFT_8M, 31
|
||||
b 201b
|
||||
|
||||
202:
|
||||
rlwinm r11, r11, 0, 0, 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1) - 1
|
||||
rlwimi r11, r10, 32 - (PAGE_SHIFT_512K - 2), 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1), 29
|
||||
lwz r11, 0(r11) /* Get the pte */
|
||||
/* concat physical page address(r11) and page offset(r10) */
|
||||
rlwimi r11, r10, 0, 32 - PAGE_SHIFT_512K, 31
|
||||
b 201b
|
||||
|
||||
144: mfspr r10, SPRN_DSISR
|
||||
rlwinm r10, r10,0,7,5 /* Clear store bit for buggy dcbst insn */
|
||||
mtspr SPRN_DSISR, r10
|
||||
|
663
arch/powerpc/kernel/kexec_elf_64.c
Normal file
663
arch/powerpc/kernel/kexec_elf_64.c
Normal file
@ -0,0 +1,663 @@
|
||||
/*
|
||||
* Load ELF vmlinux file for the kexec_file_load syscall.
|
||||
*
|
||||
* Copyright (C) 2004 Adam Litke (agl@us.ibm.com)
|
||||
* Copyright (C) 2004 IBM Corp.
|
||||
* Copyright (C) 2005 R Sharada (sharada@in.ibm.com)
|
||||
* Copyright (C) 2006 Mohan Kumar M (mohan@in.ibm.com)
|
||||
* Copyright (C) 2016 IBM Corporation
|
||||
*
|
||||
* Based on kexec-tools' kexec-elf-exec.c and kexec-elf-ppc64.c.
|
||||
* Heavily modified for the kernel by
|
||||
* Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>.
|
||||
*
|
||||
* 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 (version 2 of the License).
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "kexec_elf: " fmt
|
||||
|
||||
#include <linux/elf.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define PURGATORY_STACK_SIZE (16 * 1024)
|
||||
|
||||
#define elf_addr_to_cpu elf64_to_cpu
|
||||
|
||||
#ifndef Elf_Rel
|
||||
#define Elf_Rel Elf64_Rel
|
||||
#endif /* Elf_Rel */
|
||||
|
||||
struct elf_info {
|
||||
/*
|
||||
* Where the ELF binary contents are kept.
|
||||
* Memory managed by the user of the struct.
|
||||
*/
|
||||
const char *buffer;
|
||||
|
||||
const struct elfhdr *ehdr;
|
||||
const struct elf_phdr *proghdrs;
|
||||
struct elf_shdr *sechdrs;
|
||||
};
|
||||
|
||||
static inline bool elf_is_elf_file(const struct elfhdr *ehdr)
|
||||
{
|
||||
return memcmp(ehdr->e_ident, ELFMAG, SELFMAG) == 0;
|
||||
}
|
||||
|
||||
static uint64_t elf64_to_cpu(const struct elfhdr *ehdr, uint64_t value)
|
||||
{
|
||||
if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
|
||||
value = le64_to_cpu(value);
|
||||
else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
|
||||
value = be64_to_cpu(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static uint16_t elf16_to_cpu(const struct elfhdr *ehdr, uint16_t value)
|
||||
{
|
||||
if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
|
||||
value = le16_to_cpu(value);
|
||||
else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
|
||||
value = be16_to_cpu(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static uint32_t elf32_to_cpu(const struct elfhdr *ehdr, uint32_t value)
|
||||
{
|
||||
if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
|
||||
value = le32_to_cpu(value);
|
||||
else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
|
||||
value = be32_to_cpu(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_is_ehdr_sane - check that it is safe to use the ELF header
|
||||
* @buf_len: size of the buffer in which the ELF file is loaded.
|
||||
*/
|
||||
static bool elf_is_ehdr_sane(const struct elfhdr *ehdr, size_t buf_len)
|
||||
{
|
||||
if (ehdr->e_phnum > 0 && ehdr->e_phentsize != sizeof(struct elf_phdr)) {
|
||||
pr_debug("Bad program header size.\n");
|
||||
return false;
|
||||
} else if (ehdr->e_shnum > 0 &&
|
||||
ehdr->e_shentsize != sizeof(struct elf_shdr)) {
|
||||
pr_debug("Bad section header size.\n");
|
||||
return false;
|
||||
} else if (ehdr->e_ident[EI_VERSION] != EV_CURRENT ||
|
||||
ehdr->e_version != EV_CURRENT) {
|
||||
pr_debug("Unknown ELF version.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ehdr->e_phoff > 0 && ehdr->e_phnum > 0) {
|
||||
size_t phdr_size;
|
||||
|
||||
/*
|
||||
* e_phnum is at most 65535 so calculating the size of the
|
||||
* program header cannot overflow.
|
||||
*/
|
||||
phdr_size = sizeof(struct elf_phdr) * ehdr->e_phnum;
|
||||
|
||||
/* Sanity check the program header table location. */
|
||||
if (ehdr->e_phoff + phdr_size < ehdr->e_phoff) {
|
||||
pr_debug("Program headers at invalid location.\n");
|
||||
return false;
|
||||
} else if (ehdr->e_phoff + phdr_size > buf_len) {
|
||||
pr_debug("Program headers truncated.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ehdr->e_shoff > 0 && ehdr->e_shnum > 0) {
|
||||
size_t shdr_size;
|
||||
|
||||
/*
|
||||
* e_shnum is at most 65536 so calculating
|
||||
* the size of the section header cannot overflow.
|
||||
*/
|
||||
shdr_size = sizeof(struct elf_shdr) * ehdr->e_shnum;
|
||||
|
||||
/* Sanity check the section header table location. */
|
||||
if (ehdr->e_shoff + shdr_size < ehdr->e_shoff) {
|
||||
pr_debug("Section headers at invalid location.\n");
|
||||
return false;
|
||||
} else if (ehdr->e_shoff + shdr_size > buf_len) {
|
||||
pr_debug("Section headers truncated.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int elf_read_ehdr(const char *buf, size_t len, struct elfhdr *ehdr)
|
||||
{
|
||||
struct elfhdr *buf_ehdr;
|
||||
|
||||
if (len < sizeof(*buf_ehdr)) {
|
||||
pr_debug("Buffer is too small to hold ELF header.\n");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
memset(ehdr, 0, sizeof(*ehdr));
|
||||
memcpy(ehdr->e_ident, buf, sizeof(ehdr->e_ident));
|
||||
if (!elf_is_elf_file(ehdr)) {
|
||||
pr_debug("No ELF header magic.\n");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
if (ehdr->e_ident[EI_CLASS] != ELF_CLASS) {
|
||||
pr_debug("Not a supported ELF class.\n");
|
||||
return -ENOEXEC;
|
||||
} else if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB &&
|
||||
ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
|
||||
pr_debug("Not a supported ELF data format.\n");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
buf_ehdr = (struct elfhdr *) buf;
|
||||
if (elf16_to_cpu(ehdr, buf_ehdr->e_ehsize) != sizeof(*buf_ehdr)) {
|
||||
pr_debug("Bad ELF header size.\n");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
ehdr->e_type = elf16_to_cpu(ehdr, buf_ehdr->e_type);
|
||||
ehdr->e_machine = elf16_to_cpu(ehdr, buf_ehdr->e_machine);
|
||||
ehdr->e_version = elf32_to_cpu(ehdr, buf_ehdr->e_version);
|
||||
ehdr->e_entry = elf_addr_to_cpu(ehdr, buf_ehdr->e_entry);
|
||||
ehdr->e_phoff = elf_addr_to_cpu(ehdr, buf_ehdr->e_phoff);
|
||||
ehdr->e_shoff = elf_addr_to_cpu(ehdr, buf_ehdr->e_shoff);
|
||||
ehdr->e_flags = elf32_to_cpu(ehdr, buf_ehdr->e_flags);
|
||||
ehdr->e_phentsize = elf16_to_cpu(ehdr, buf_ehdr->e_phentsize);
|
||||
ehdr->e_phnum = elf16_to_cpu(ehdr, buf_ehdr->e_phnum);
|
||||
ehdr->e_shentsize = elf16_to_cpu(ehdr, buf_ehdr->e_shentsize);
|
||||
ehdr->e_shnum = elf16_to_cpu(ehdr, buf_ehdr->e_shnum);
|
||||
ehdr->e_shstrndx = elf16_to_cpu(ehdr, buf_ehdr->e_shstrndx);
|
||||
|
||||
return elf_is_ehdr_sane(ehdr, len) ? 0 : -ENOEXEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_is_phdr_sane - check that it is safe to use the program header
|
||||
* @buf_len: size of the buffer in which the ELF file is loaded.
|
||||
*/
|
||||
static bool elf_is_phdr_sane(const struct elf_phdr *phdr, size_t buf_len)
|
||||
{
|
||||
|
||||
if (phdr->p_offset + phdr->p_filesz < phdr->p_offset) {
|
||||
pr_debug("ELF segment location wraps around.\n");
|
||||
return false;
|
||||
} else if (phdr->p_offset + phdr->p_filesz > buf_len) {
|
||||
pr_debug("ELF segment not in file.\n");
|
||||
return false;
|
||||
} else if (phdr->p_paddr + phdr->p_memsz < phdr->p_paddr) {
|
||||
pr_debug("ELF segment address wraps around.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int elf_read_phdr(const char *buf, size_t len, struct elf_info *elf_info,
|
||||
int idx)
|
||||
{
|
||||
/* Override the const in proghdrs, we are the ones doing the loading. */
|
||||
struct elf_phdr *phdr = (struct elf_phdr *) &elf_info->proghdrs[idx];
|
||||
const char *pbuf;
|
||||
struct elf_phdr *buf_phdr;
|
||||
|
||||
pbuf = buf + elf_info->ehdr->e_phoff + (idx * sizeof(*buf_phdr));
|
||||
buf_phdr = (struct elf_phdr *) pbuf;
|
||||
|
||||
phdr->p_type = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_type);
|
||||
phdr->p_offset = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_offset);
|
||||
phdr->p_paddr = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_paddr);
|
||||
phdr->p_vaddr = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_vaddr);
|
||||
phdr->p_flags = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_flags);
|
||||
|
||||
/*
|
||||
* The following fields have a type equivalent to Elf_Addr
|
||||
* both in 32 bit and 64 bit ELF.
|
||||
*/
|
||||
phdr->p_filesz = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_filesz);
|
||||
phdr->p_memsz = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_memsz);
|
||||
phdr->p_align = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_align);
|
||||
|
||||
return elf_is_phdr_sane(phdr, len) ? 0 : -ENOEXEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_read_phdrs - read the program headers from the buffer
|
||||
*
|
||||
* This function assumes that the program header table was checked for sanity.
|
||||
* Use elf_is_ehdr_sane() if it wasn't.
|
||||
*/
|
||||
static int elf_read_phdrs(const char *buf, size_t len,
|
||||
struct elf_info *elf_info)
|
||||
{
|
||||
size_t phdr_size, i;
|
||||
const struct elfhdr *ehdr = elf_info->ehdr;
|
||||
|
||||
/*
|
||||
* e_phnum is at most 65535 so calculating the size of the
|
||||
* program header cannot overflow.
|
||||
*/
|
||||
phdr_size = sizeof(struct elf_phdr) * ehdr->e_phnum;
|
||||
|
||||
elf_info->proghdrs = kzalloc(phdr_size, GFP_KERNEL);
|
||||
if (!elf_info->proghdrs)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ehdr->e_phnum; i++) {
|
||||
int ret;
|
||||
|
||||
ret = elf_read_phdr(buf, len, elf_info, i);
|
||||
if (ret) {
|
||||
kfree(elf_info->proghdrs);
|
||||
elf_info->proghdrs = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_is_shdr_sane - check that it is safe to use the section header
|
||||
* @buf_len: size of the buffer in which the ELF file is loaded.
|
||||
*/
|
||||
static bool elf_is_shdr_sane(const struct elf_shdr *shdr, size_t buf_len)
|
||||
{
|
||||
bool size_ok;
|
||||
|
||||
/* SHT_NULL headers have undefined values, so we can't check them. */
|
||||
if (shdr->sh_type == SHT_NULL)
|
||||
return true;
|
||||
|
||||
/* Now verify sh_entsize */
|
||||
switch (shdr->sh_type) {
|
||||
case SHT_SYMTAB:
|
||||
size_ok = shdr->sh_entsize == sizeof(Elf_Sym);
|
||||
break;
|
||||
case SHT_RELA:
|
||||
size_ok = shdr->sh_entsize == sizeof(Elf_Rela);
|
||||
break;
|
||||
case SHT_DYNAMIC:
|
||||
size_ok = shdr->sh_entsize == sizeof(Elf_Dyn);
|
||||
break;
|
||||
case SHT_REL:
|
||||
size_ok = shdr->sh_entsize == sizeof(Elf_Rel);
|
||||
break;
|
||||
case SHT_NOTE:
|
||||
case SHT_PROGBITS:
|
||||
case SHT_HASH:
|
||||
case SHT_NOBITS:
|
||||
default:
|
||||
/*
|
||||
* This is a section whose entsize requirements
|
||||
* I don't care about. If I don't know about
|
||||
* the section I can't care about it's entsize
|
||||
* requirements.
|
||||
*/
|
||||
size_ok = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!size_ok) {
|
||||
pr_debug("ELF section with wrong entry size.\n");
|
||||
return false;
|
||||
} else if (shdr->sh_addr + shdr->sh_size < shdr->sh_addr) {
|
||||
pr_debug("ELF section address wraps around.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (shdr->sh_type != SHT_NOBITS) {
|
||||
if (shdr->sh_offset + shdr->sh_size < shdr->sh_offset) {
|
||||
pr_debug("ELF section location wraps around.\n");
|
||||
return false;
|
||||
} else if (shdr->sh_offset + shdr->sh_size > buf_len) {
|
||||
pr_debug("ELF section not in file.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int elf_read_shdr(const char *buf, size_t len, struct elf_info *elf_info,
|
||||
int idx)
|
||||
{
|
||||
struct elf_shdr *shdr = &elf_info->sechdrs[idx];
|
||||
const struct elfhdr *ehdr = elf_info->ehdr;
|
||||
const char *sbuf;
|
||||
struct elf_shdr *buf_shdr;
|
||||
|
||||
sbuf = buf + ehdr->e_shoff + idx * sizeof(*buf_shdr);
|
||||
buf_shdr = (struct elf_shdr *) sbuf;
|
||||
|
||||
shdr->sh_name = elf32_to_cpu(ehdr, buf_shdr->sh_name);
|
||||
shdr->sh_type = elf32_to_cpu(ehdr, buf_shdr->sh_type);
|
||||
shdr->sh_addr = elf_addr_to_cpu(ehdr, buf_shdr->sh_addr);
|
||||
shdr->sh_offset = elf_addr_to_cpu(ehdr, buf_shdr->sh_offset);
|
||||
shdr->sh_link = elf32_to_cpu(ehdr, buf_shdr->sh_link);
|
||||
shdr->sh_info = elf32_to_cpu(ehdr, buf_shdr->sh_info);
|
||||
|
||||
/*
|
||||
* The following fields have a type equivalent to Elf_Addr
|
||||
* both in 32 bit and 64 bit ELF.
|
||||
*/
|
||||
shdr->sh_flags = elf_addr_to_cpu(ehdr, buf_shdr->sh_flags);
|
||||
shdr->sh_size = elf_addr_to_cpu(ehdr, buf_shdr->sh_size);
|
||||
shdr->sh_addralign = elf_addr_to_cpu(ehdr, buf_shdr->sh_addralign);
|
||||
shdr->sh_entsize = elf_addr_to_cpu(ehdr, buf_shdr->sh_entsize);
|
||||
|
||||
return elf_is_shdr_sane(shdr, len) ? 0 : -ENOEXEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_read_shdrs - read the section headers from the buffer
|
||||
*
|
||||
* This function assumes that the section header table was checked for sanity.
|
||||
* Use elf_is_ehdr_sane() if it wasn't.
|
||||
*/
|
||||
static int elf_read_shdrs(const char *buf, size_t len,
|
||||
struct elf_info *elf_info)
|
||||
{
|
||||
size_t shdr_size, i;
|
||||
|
||||
/*
|
||||
* e_shnum is at most 65536 so calculating
|
||||
* the size of the section header cannot overflow.
|
||||
*/
|
||||
shdr_size = sizeof(struct elf_shdr) * elf_info->ehdr->e_shnum;
|
||||
|
||||
elf_info->sechdrs = kzalloc(shdr_size, GFP_KERNEL);
|
||||
if (!elf_info->sechdrs)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < elf_info->ehdr->e_shnum; i++) {
|
||||
int ret;
|
||||
|
||||
ret = elf_read_shdr(buf, len, elf_info, i);
|
||||
if (ret) {
|
||||
kfree(elf_info->sechdrs);
|
||||
elf_info->sechdrs = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_read_from_buffer - read ELF file and sets up ELF header and ELF info
|
||||
* @buf: Buffer to read ELF file from.
|
||||
* @len: Size of @buf.
|
||||
* @ehdr: Pointer to existing struct which will be populated.
|
||||
* @elf_info: Pointer to existing struct which will be populated.
|
||||
*
|
||||
* This function allows reading ELF files with different byte order than
|
||||
* the kernel, byte-swapping the fields as needed.
|
||||
*
|
||||
* Return:
|
||||
* On success returns 0, and the caller should call elf_free_info(elf_info) to
|
||||
* free the memory allocated for the section and program headers.
|
||||
*/
|
||||
int elf_read_from_buffer(const char *buf, size_t len, struct elfhdr *ehdr,
|
||||
struct elf_info *elf_info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = elf_read_ehdr(buf, len, ehdr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
elf_info->buffer = buf;
|
||||
elf_info->ehdr = ehdr;
|
||||
if (ehdr->e_phoff > 0 && ehdr->e_phnum > 0) {
|
||||
ret = elf_read_phdrs(buf, len, elf_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (ehdr->e_shoff > 0 && ehdr->e_shnum > 0) {
|
||||
ret = elf_read_shdrs(buf, len, elf_info);
|
||||
if (ret) {
|
||||
kfree(elf_info->proghdrs);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_free_info - free memory allocated by elf_read_from_buffer
|
||||
*/
|
||||
void elf_free_info(struct elf_info *elf_info)
|
||||
{
|
||||
kfree(elf_info->proghdrs);
|
||||
kfree(elf_info->sechdrs);
|
||||
memset(elf_info, 0, sizeof(*elf_info));
|
||||
}
|
||||
/**
|
||||
* build_elf_exec_info - read ELF executable and check that we can use it
|
||||
*/
|
||||
static int build_elf_exec_info(const char *buf, size_t len, struct elfhdr *ehdr,
|
||||
struct elf_info *elf_info)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
ret = elf_read_from_buffer(buf, len, ehdr, elf_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Big endian vmlinux has type ET_DYN. */
|
||||
if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
|
||||
pr_err("Not an ELF executable.\n");
|
||||
goto error;
|
||||
} else if (!elf_info->proghdrs) {
|
||||
pr_err("No ELF program header.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < ehdr->e_phnum; i++) {
|
||||
/*
|
||||
* Kexec does not support loading interpreters.
|
||||
* In addition this check keeps us from attempting
|
||||
* to kexec ordinay executables.
|
||||
*/
|
||||
if (elf_info->proghdrs[i].p_type == PT_INTERP) {
|
||||
pr_err("Requires an ELF interpreter.\n");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
elf_free_info(elf_info);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
static int elf64_probe(const char *buf, unsigned long len)
|
||||
{
|
||||
struct elfhdr ehdr;
|
||||
struct elf_info elf_info;
|
||||
int ret;
|
||||
|
||||
ret = build_elf_exec_info(buf, len, &ehdr, &elf_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
elf_free_info(&elf_info);
|
||||
|
||||
return elf_check_arch(&ehdr) ? 0 : -ENOEXEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_exec_load - load ELF executable image
|
||||
* @lowest_load_addr: On return, will be the address where the first PT_LOAD
|
||||
* section will be loaded in memory.
|
||||
*
|
||||
* Return:
|
||||
* 0 on success, negative value on failure.
|
||||
*/
|
||||
static int elf_exec_load(struct kimage *image, struct elfhdr *ehdr,
|
||||
struct elf_info *elf_info,
|
||||
unsigned long *lowest_load_addr)
|
||||
{
|
||||
unsigned long base = 0, lowest_addr = UINT_MAX;
|
||||
int ret;
|
||||
size_t i;
|
||||
struct kexec_buf kbuf = { .image = image, .buf_max = ppc64_rma_size,
|
||||
.top_down = false };
|
||||
|
||||
/* Read in the PT_LOAD segments. */
|
||||
for (i = 0; i < ehdr->e_phnum; i++) {
|
||||
unsigned long load_addr;
|
||||
size_t size;
|
||||
const struct elf_phdr *phdr;
|
||||
|
||||
phdr = &elf_info->proghdrs[i];
|
||||
if (phdr->p_type != PT_LOAD)
|
||||
continue;
|
||||
|
||||
size = phdr->p_filesz;
|
||||
if (size > phdr->p_memsz)
|
||||
size = phdr->p_memsz;
|
||||
|
||||
kbuf.buffer = (void *) elf_info->buffer + phdr->p_offset;
|
||||
kbuf.bufsz = size;
|
||||
kbuf.memsz = phdr->p_memsz;
|
||||
kbuf.buf_align = phdr->p_align;
|
||||
kbuf.buf_min = phdr->p_paddr + base;
|
||||
ret = kexec_add_buffer(&kbuf);
|
||||
if (ret)
|
||||
goto out;
|
||||
load_addr = kbuf.mem;
|
||||
|
||||
if (load_addr < lowest_addr)
|
||||
lowest_addr = load_addr;
|
||||
}
|
||||
|
||||
/* Update entry point to reflect new load address. */
|
||||
ehdr->e_entry += base;
|
||||
|
||||
*lowest_load_addr = lowest_addr;
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *elf64_load(struct kimage *image, char *kernel_buf,
|
||||
unsigned long kernel_len, char *initrd,
|
||||
unsigned long initrd_len, char *cmdline,
|
||||
unsigned long cmdline_len)
|
||||
{
|
||||
int ret;
|
||||
unsigned int fdt_size;
|
||||
unsigned long kernel_load_addr, purgatory_load_addr;
|
||||
unsigned long initrd_load_addr = 0, fdt_load_addr;
|
||||
void *fdt;
|
||||
const void *slave_code;
|
||||
struct elfhdr ehdr;
|
||||
struct elf_info elf_info;
|
||||
struct kexec_buf kbuf = { .image = image, .buf_min = 0,
|
||||
.buf_max = ppc64_rma_size };
|
||||
|
||||
ret = build_elf_exec_info(kernel_buf, kernel_len, &ehdr, &elf_info);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = elf_exec_load(image, &ehdr, &elf_info, &kernel_load_addr);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
pr_debug("Loaded the kernel at 0x%lx\n", kernel_load_addr);
|
||||
|
||||
ret = kexec_load_purgatory(image, 0, ppc64_rma_size, true,
|
||||
&purgatory_load_addr);
|
||||
if (ret) {
|
||||
pr_err("Loading purgatory failed.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
pr_debug("Loaded purgatory at 0x%lx\n", purgatory_load_addr);
|
||||
|
||||
if (initrd != NULL) {
|
||||
kbuf.buffer = initrd;
|
||||
kbuf.bufsz = kbuf.memsz = initrd_len;
|
||||
kbuf.buf_align = PAGE_SIZE;
|
||||
kbuf.top_down = false;
|
||||
ret = kexec_add_buffer(&kbuf);
|
||||
if (ret)
|
||||
goto out;
|
||||
initrd_load_addr = kbuf.mem;
|
||||
|
||||
pr_debug("Loaded initrd at 0x%lx\n", initrd_load_addr);
|
||||
}
|
||||
|
||||
fdt_size = fdt_totalsize(initial_boot_params) * 2;
|
||||
fdt = kmalloc(fdt_size, GFP_KERNEL);
|
||||
if (!fdt) {
|
||||
pr_err("Not enough memory for the device tree.\n");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
ret = fdt_open_into(initial_boot_params, fdt, fdt_size);
|
||||
if (ret < 0) {
|
||||
pr_err("Error setting up the new device tree.\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = setup_new_fdt(fdt, initrd_load_addr, initrd_len, cmdline);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
fdt_pack(fdt);
|
||||
|
||||
kbuf.buffer = fdt;
|
||||
kbuf.bufsz = kbuf.memsz = fdt_size;
|
||||
kbuf.buf_align = PAGE_SIZE;
|
||||
kbuf.top_down = true;
|
||||
ret = kexec_add_buffer(&kbuf);
|
||||
if (ret)
|
||||
goto out;
|
||||
fdt_load_addr = kbuf.mem;
|
||||
|
||||
pr_debug("Loaded device tree at 0x%lx\n", fdt_load_addr);
|
||||
|
||||
slave_code = elf_info.buffer + elf_info.proghdrs[0].p_offset;
|
||||
ret = setup_purgatory(image, slave_code, fdt, kernel_load_addr,
|
||||
fdt_load_addr);
|
||||
if (ret)
|
||||
pr_err("Error setting up the purgatory.\n");
|
||||
|
||||
out:
|
||||
elf_free_info(&elf_info);
|
||||
|
||||
/* Make kimage_file_post_load_cleanup free the fdt buffer for us. */
|
||||
return ret ? ERR_PTR(ret) : fdt;
|
||||
}
|
||||
|
||||
struct kexec_file_ops kexec_elf64_ops = {
|
||||
.probe = elf64_probe,
|
||||
.load = elf64_load,
|
||||
};
|
@ -140,13 +140,16 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
|
||||
regs->link = (unsigned long)kretprobe_trampoline;
|
||||
}
|
||||
|
||||
static int __kprobes kprobe_handler(struct pt_regs *regs)
|
||||
int __kprobes kprobe_handler(struct pt_regs *regs)
|
||||
{
|
||||
struct kprobe *p;
|
||||
int ret = 0;
|
||||
unsigned int *addr = (unsigned int *)regs->nip;
|
||||
struct kprobe_ctlblk *kcb;
|
||||
|
||||
if (user_mode(regs))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* We don't want to be preempted for the entire
|
||||
* duration of kprobe processing
|
||||
@ -359,12 +362,12 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
|
||||
* single-stepped a copy of the instruction. The address of this
|
||||
* copy is p->ainsn.insn.
|
||||
*/
|
||||
static int __kprobes post_kprobe_handler(struct pt_regs *regs)
|
||||
int __kprobes kprobe_post_handler(struct pt_regs *regs)
|
||||
{
|
||||
struct kprobe *cur = kprobe_running();
|
||||
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
||||
|
||||
if (!cur)
|
||||
if (!cur || user_mode(regs))
|
||||
return 0;
|
||||
|
||||
/* make sure we got here for instruction we have a kprobe on */
|
||||
@ -449,7 +452,7 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
|
||||
* zero, try to fix up.
|
||||
*/
|
||||
if ((entry = search_exception_tables(regs->nip)) != NULL) {
|
||||
regs->nip = entry->fixup;
|
||||
regs->nip = extable_fixup(entry);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -470,25 +473,7 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
|
||||
int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
|
||||
unsigned long val, void *data)
|
||||
{
|
||||
struct die_args *args = (struct die_args *)data;
|
||||
int ret = NOTIFY_DONE;
|
||||
|
||||
if (args->regs && user_mode(args->regs))
|
||||
return ret;
|
||||
|
||||
switch (val) {
|
||||
case DIE_BPT:
|
||||
if (kprobe_handler(args->regs))
|
||||
ret = NOTIFY_STOP;
|
||||
break;
|
||||
case DIE_SSTEP:
|
||||
if (post_kprobe_handler(args->regs))
|
||||
ret = NOTIFY_STOP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
unsigned long arch_deref_entry_point(void *entry)
|
||||
|
@ -310,7 +310,7 @@ void default_machine_kexec(struct kimage *image)
|
||||
if (!kdump_in_progress())
|
||||
kexec_prepare_cpus();
|
||||
|
||||
pr_debug("kexec: Starting switchover sequence.\n");
|
||||
printk("kexec: Starting switchover sequence.\n");
|
||||
|
||||
/* switch to a staticly allocated stack. Based on irq stack code.
|
||||
* We setup preempt_count to avoid using VMX in memcpy.
|
||||
|
338
arch/powerpc/kernel/machine_kexec_file_64.c
Normal file
338
arch/powerpc/kernel/machine_kexec_file_64.c
Normal file
@ -0,0 +1,338 @@
|
||||
/*
|
||||
* ppc64 code to implement the kexec_file_load syscall
|
||||
*
|
||||
* Copyright (C) 2004 Adam Litke (agl@us.ibm.com)
|
||||
* Copyright (C) 2004 IBM Corp.
|
||||
* Copyright (C) 2004,2005 Milton D Miller II, IBM Corporation
|
||||
* Copyright (C) 2005 R Sharada (sharada@in.ibm.com)
|
||||
* Copyright (C) 2006 Mohan Kumar M (mohan@in.ibm.com)
|
||||
* Copyright (C) 2016 IBM Corporation
|
||||
*
|
||||
* Based on kexec-tools' kexec-elf-ppc64.c, fs2dt.c.
|
||||
* Heavily modified for the kernel by
|
||||
* Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>.
|
||||
*
|
||||
* 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 (version 2 of the License).
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/libfdt.h>
|
||||
|
||||
#define SLAVE_CODE_SIZE 256
|
||||
|
||||
static struct kexec_file_ops *kexec_file_loaders[] = {
|
||||
&kexec_elf64_ops,
|
||||
};
|
||||
|
||||
int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
|
||||
unsigned long buf_len)
|
||||
{
|
||||
int i, ret = -ENOEXEC;
|
||||
struct kexec_file_ops *fops;
|
||||
|
||||
/* We don't support crash kernels yet. */
|
||||
if (image->type == KEXEC_TYPE_CRASH)
|
||||
return -ENOTSUPP;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(kexec_file_loaders); i++) {
|
||||
fops = kexec_file_loaders[i];
|
||||
if (!fops || !fops->probe)
|
||||
continue;
|
||||
|
||||
ret = fops->probe(buf, buf_len);
|
||||
if (!ret) {
|
||||
image->fops = fops;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *arch_kexec_kernel_image_load(struct kimage *image)
|
||||
{
|
||||
if (!image->fops || !image->fops->load)
|
||||
return ERR_PTR(-ENOEXEC);
|
||||
|
||||
return image->fops->load(image, image->kernel_buf,
|
||||
image->kernel_buf_len, image->initrd_buf,
|
||||
image->initrd_buf_len, image->cmdline_buf,
|
||||
image->cmdline_buf_len);
|
||||
}
|
||||
|
||||
int arch_kimage_file_post_load_cleanup(struct kimage *image)
|
||||
{
|
||||
if (!image->fops || !image->fops->cleanup)
|
||||
return 0;
|
||||
|
||||
return image->fops->cleanup(image->image_loader_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* arch_kexec_walk_mem - call func(data) for each unreserved memory block
|
||||
* @kbuf: Context info for the search. Also passed to @func.
|
||||
* @func: Function to call for each memory block.
|
||||
*
|
||||
* This function is used by kexec_add_buffer and kexec_locate_mem_hole
|
||||
* to find unreserved memory to load kexec segments into.
|
||||
*
|
||||
* Return: The memory walk will stop when func returns a non-zero value
|
||||
* and that value will be returned. If all free regions are visited without
|
||||
* func returning non-zero, then zero will be returned.
|
||||
*/
|
||||
int arch_kexec_walk_mem(struct kexec_buf *kbuf, int (*func)(u64, u64, void *))
|
||||
{
|
||||
int ret = 0;
|
||||
u64 i;
|
||||
phys_addr_t mstart, mend;
|
||||
|
||||
if (kbuf->top_down) {
|
||||
for_each_free_mem_range_reverse(i, NUMA_NO_NODE, 0,
|
||||
&mstart, &mend, NULL) {
|
||||
/*
|
||||
* In memblock, end points to the first byte after the
|
||||
* range while in kexec, end points to the last byte
|
||||
* in the range.
|
||||
*/
|
||||
ret = func(mstart, mend - 1, kbuf);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for_each_free_mem_range(i, NUMA_NO_NODE, 0, &mstart, &mend,
|
||||
NULL) {
|
||||
/*
|
||||
* In memblock, end points to the first byte after the
|
||||
* range while in kexec, end points to the last byte
|
||||
* in the range.
|
||||
*/
|
||||
ret = func(mstart, mend - 1, kbuf);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* setup_purgatory - initialize the purgatory's global variables
|
||||
* @image: kexec image.
|
||||
* @slave_code: Slave code for the purgatory.
|
||||
* @fdt: Flattened device tree for the next kernel.
|
||||
* @kernel_load_addr: Address where the kernel is loaded.
|
||||
* @fdt_load_addr: Address where the flattened device tree is loaded.
|
||||
*
|
||||
* Return: 0 on success, or negative errno on error.
|
||||
*/
|
||||
int setup_purgatory(struct kimage *image, const void *slave_code,
|
||||
const void *fdt, unsigned long kernel_load_addr,
|
||||
unsigned long fdt_load_addr)
|
||||
{
|
||||
unsigned int *slave_code_buf, master_entry;
|
||||
int ret;
|
||||
|
||||
slave_code_buf = kmalloc(SLAVE_CODE_SIZE, GFP_KERNEL);
|
||||
if (!slave_code_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Get the slave code from the new kernel and put it in purgatory. */
|
||||
ret = kexec_purgatory_get_set_symbol(image, "purgatory_start",
|
||||
slave_code_buf, SLAVE_CODE_SIZE,
|
||||
true);
|
||||
if (ret) {
|
||||
kfree(slave_code_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
master_entry = slave_code_buf[0];
|
||||
memcpy(slave_code_buf, slave_code, SLAVE_CODE_SIZE);
|
||||
slave_code_buf[0] = master_entry;
|
||||
ret = kexec_purgatory_get_set_symbol(image, "purgatory_start",
|
||||
slave_code_buf, SLAVE_CODE_SIZE,
|
||||
false);
|
||||
kfree(slave_code_buf);
|
||||
|
||||
ret = kexec_purgatory_get_set_symbol(image, "kernel", &kernel_load_addr,
|
||||
sizeof(kernel_load_addr), false);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = kexec_purgatory_get_set_symbol(image, "dt_offset", &fdt_load_addr,
|
||||
sizeof(fdt_load_addr), false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* delete_fdt_mem_rsv - delete memory reservation with given address and size
|
||||
*
|
||||
* Return: 0 on success, or negative errno on error.
|
||||
*/
|
||||
static int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size)
|
||||
{
|
||||
int i, ret, num_rsvs = fdt_num_mem_rsv(fdt);
|
||||
|
||||
for (i = 0; i < num_rsvs; i++) {
|
||||
uint64_t rsv_start, rsv_size;
|
||||
|
||||
ret = fdt_get_mem_rsv(fdt, i, &rsv_start, &rsv_size);
|
||||
if (ret) {
|
||||
pr_err("Malformed device tree.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (rsv_start == start && rsv_size == size) {
|
||||
ret = fdt_del_mem_rsv(fdt, i);
|
||||
if (ret) {
|
||||
pr_err("Error deleting device tree reservation.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* setup_new_fdt - modify /chosen and memory reservation for the next kernel
|
||||
* @fdt: Flattened device tree for the next kernel.
|
||||
* @initrd_load_addr: Address where the next initrd will be loaded.
|
||||
* @initrd_len: Size of the next initrd, or 0 if there will be none.
|
||||
* @cmdline: Command line for the next kernel, or NULL if there will
|
||||
* be none.
|
||||
*
|
||||
* Return: 0 on success, or negative errno on error.
|
||||
*/
|
||||
int setup_new_fdt(void *fdt, unsigned long initrd_load_addr,
|
||||
unsigned long initrd_len, const char *cmdline)
|
||||
{
|
||||
int ret, chosen_node;
|
||||
const void *prop;
|
||||
|
||||
/* Remove memory reservation for the current device tree. */
|
||||
ret = delete_fdt_mem_rsv(fdt, __pa(initial_boot_params),
|
||||
fdt_totalsize(initial_boot_params));
|
||||
if (ret == 0)
|
||||
pr_debug("Removed old device tree reservation.\n");
|
||||
else if (ret != -ENOENT)
|
||||
return ret;
|
||||
|
||||
chosen_node = fdt_path_offset(fdt, "/chosen");
|
||||
if (chosen_node == -FDT_ERR_NOTFOUND) {
|
||||
chosen_node = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"),
|
||||
"chosen");
|
||||
if (chosen_node < 0) {
|
||||
pr_err("Error creating /chosen.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (chosen_node < 0) {
|
||||
pr_err("Malformed device tree: error reading /chosen.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Did we boot using an initrd? */
|
||||
prop = fdt_getprop(fdt, chosen_node, "linux,initrd-start", NULL);
|
||||
if (prop) {
|
||||
uint64_t tmp_start, tmp_end, tmp_size;
|
||||
|
||||
tmp_start = fdt64_to_cpu(*((const fdt64_t *) prop));
|
||||
|
||||
prop = fdt_getprop(fdt, chosen_node, "linux,initrd-end", NULL);
|
||||
if (!prop) {
|
||||
pr_err("Malformed device tree.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
tmp_end = fdt64_to_cpu(*((const fdt64_t *) prop));
|
||||
|
||||
/*
|
||||
* kexec reserves exact initrd size, while firmware may
|
||||
* reserve a multiple of PAGE_SIZE, so check for both.
|
||||
*/
|
||||
tmp_size = tmp_end - tmp_start;
|
||||
ret = delete_fdt_mem_rsv(fdt, tmp_start, tmp_size);
|
||||
if (ret == -ENOENT)
|
||||
ret = delete_fdt_mem_rsv(fdt, tmp_start,
|
||||
round_up(tmp_size, PAGE_SIZE));
|
||||
if (ret == 0)
|
||||
pr_debug("Removed old initrd reservation.\n");
|
||||
else if (ret != -ENOENT)
|
||||
return ret;
|
||||
|
||||
/* If there's no new initrd, delete the old initrd's info. */
|
||||
if (initrd_len == 0) {
|
||||
ret = fdt_delprop(fdt, chosen_node,
|
||||
"linux,initrd-start");
|
||||
if (ret) {
|
||||
pr_err("Error deleting linux,initrd-start.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = fdt_delprop(fdt, chosen_node, "linux,initrd-end");
|
||||
if (ret) {
|
||||
pr_err("Error deleting linux,initrd-end.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (initrd_len) {
|
||||
ret = fdt_setprop_u64(fdt, chosen_node,
|
||||
"linux,initrd-start",
|
||||
initrd_load_addr);
|
||||
if (ret < 0) {
|
||||
pr_err("Error setting up the new device tree.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* initrd-end is the first address after the initrd image. */
|
||||
ret = fdt_setprop_u64(fdt, chosen_node, "linux,initrd-end",
|
||||
initrd_load_addr + initrd_len);
|
||||
if (ret < 0) {
|
||||
pr_err("Error setting up the new device tree.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = fdt_add_mem_rsv(fdt, initrd_load_addr, initrd_len);
|
||||
if (ret) {
|
||||
pr_err("Error reserving initrd memory: %s\n",
|
||||
fdt_strerror(ret));
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmdline != NULL) {
|
||||
ret = fdt_setprop_string(fdt, chosen_node, "bootargs", cmdline);
|
||||
if (ret < 0) {
|
||||
pr_err("Error setting up the new device tree.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
ret = fdt_delprop(fdt, chosen_node, "bootargs");
|
||||
if (ret && ret != -FDT_ERR_NOTFOUND) {
|
||||
pr_err("Error deleting bootargs.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = fdt_setprop(fdt, chosen_node, "linux,booted-from-kexec", NULL, 0);
|
||||
if (ret) {
|
||||
pr_err("Error setting up the new device tree.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -72,7 +72,6 @@ void save_mce_event(struct pt_regs *regs, long handled,
|
||||
struct mce_error_info *mce_err,
|
||||
uint64_t nip, uint64_t addr)
|
||||
{
|
||||
uint64_t srr1;
|
||||
int index = __this_cpu_inc_return(mce_nest_count) - 1;
|
||||
struct machine_check_event *mce = this_cpu_ptr(&mce_event[index]);
|
||||
|
||||
@ -99,8 +98,6 @@ void save_mce_event(struct pt_regs *regs, long handled,
|
||||
mce->disposition = MCE_DISPOSITION_NOT_RECOVERED;
|
||||
mce->severity = MCE_SEV_ERROR_SYNC;
|
||||
|
||||
srr1 = regs->msr;
|
||||
|
||||
/*
|
||||
* Populate the mce error_type and type-specific error_type.
|
||||
*/
|
||||
|
@ -614,7 +614,7 @@ _GLOBAL(start_secondary_resume)
|
||||
_GLOBAL(__main)
|
||||
blr
|
||||
|
||||
#ifdef CONFIG_KEXEC
|
||||
#ifdef CONFIG_KEXEC_CORE
|
||||
/*
|
||||
* Must be relocatable PIC code callable as a C function.
|
||||
*/
|
||||
|
@ -478,7 +478,7 @@ _GLOBAL(kexec_wait)
|
||||
addi r5,r5,kexec_flag-1b
|
||||
|
||||
99: HMT_LOW
|
||||
#ifdef CONFIG_KEXEC /* use no memory without kexec */
|
||||
#ifdef CONFIG_KEXEC_CORE /* use no memory without kexec */
|
||||
lwz r4,0(r5)
|
||||
cmpwi 0,r4,0
|
||||
beq 99b
|
||||
@ -503,7 +503,7 @@ kexec_flag:
|
||||
.long 0
|
||||
|
||||
|
||||
#ifdef CONFIG_KEXEC
|
||||
#ifdef CONFIG_KEXEC_CORE
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
/*
|
||||
* BOOK3E has no real MMU mode, so we have to setup the initial TLB
|
||||
@ -716,4 +716,4 @@ _GLOBAL(kexec_sequence)
|
||||
mtlr 4
|
||||
li r5,0
|
||||
blr /* image->start(physid, image->start, 0); */
|
||||
#endif /* CONFIG_KEXEC */
|
||||
#endif /* CONFIG_KEXEC_CORE */
|
||||
|
@ -652,6 +652,11 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
|
||||
*location = value - (unsigned long)location;
|
||||
break;
|
||||
|
||||
case R_PPC64_REL32:
|
||||
/* 32 bits relative (used by relative exception tables) */
|
||||
*(u32 *)location = value - (unsigned long)location;
|
||||
break;
|
||||
|
||||
case R_PPC64_TOCSAVE:
|
||||
/*
|
||||
* Marker reloc indicates we don't have to save r2.
|
||||
|
@ -114,11 +114,6 @@ static struct platform_driver of_pci_phb_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static __init int of_pci_phb_init(void)
|
||||
{
|
||||
return platform_driver_register(&of_pci_phb_driver);
|
||||
}
|
||||
|
||||
device_initcall(of_pci_phb_init);
|
||||
builtin_platform_driver(of_pci_phb_driver);
|
||||
|
||||
#endif /* CONFIG_PPC_OF_PLATFORM_PCI */
|
||||
|
@ -64,6 +64,12 @@
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/kdebug.h>
|
||||
|
||||
#ifdef CONFIG_CC_STACKPROTECTOR
|
||||
#include <linux/stackprotector.h>
|
||||
unsigned long __stack_chk_guard __read_mostly;
|
||||
EXPORT_SYMBOL(__stack_chk_guard);
|
||||
#endif
|
||||
|
||||
/* Transactional Memory debug */
|
||||
#ifdef TM_DEBUG_SW
|
||||
#define TM_DEBUG(x...) printk(KERN_INFO x)
|
||||
@ -1051,14 +1057,6 @@ static inline void save_sprs(struct thread_struct *t)
|
||||
*/
|
||||
t->tar = mfspr(SPRN_TAR);
|
||||
}
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_300)) {
|
||||
/* Conditionally save Load Monitor registers, if enabled */
|
||||
if (t->fscr & FSCR_LM) {
|
||||
t->lmrr = mfspr(SPRN_LMRR);
|
||||
t->lmser = mfspr(SPRN_LMSER);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1094,16 +1092,6 @@ static inline void restore_sprs(struct thread_struct *old_thread,
|
||||
if (old_thread->tar != new_thread->tar)
|
||||
mtspr(SPRN_TAR, new_thread->tar);
|
||||
}
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_300)) {
|
||||
/* Conditionally restore Load Monitor registers, if enabled */
|
||||
if (new_thread->fscr & FSCR_LM) {
|
||||
if (old_thread->lmrr != new_thread->lmrr)
|
||||
mtspr(SPRN_LMRR, new_thread->lmrr);
|
||||
if (old_thread->lmser != new_thread->lmser)
|
||||
mtspr(SPRN_LMSER, new_thread->lmser);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -156,21 +156,22 @@ static struct ibm_pa_feature {
|
||||
unsigned char pabit; /* bit number (big-endian) */
|
||||
unsigned char invert; /* if 1, pa bit set => clear feature */
|
||||
} ibm_pa_features[] __initdata = {
|
||||
{0, 0, PPC_FEATURE_HAS_MMU, 0, 0, 0, 0},
|
||||
{0, 0, PPC_FEATURE_HAS_FPU, 0, 0, 1, 0},
|
||||
{CPU_FTR_CTRL, 0, 0, 0, 0, 3, 0},
|
||||
{CPU_FTR_NOEXECUTE, 0, 0, 0, 0, 6, 0},
|
||||
{CPU_FTR_NODSISRALIGN, 0, 0, 0, 1, 1, 1},
|
||||
{0, MMU_FTR_CI_LARGE_PAGE, 0, 0, 1, 2, 0},
|
||||
{CPU_FTR_REAL_LE, 0, PPC_FEATURE_TRUE_LE, 0, 5, 0, 0},
|
||||
{ .pabyte = 0, .pabit = 0, .cpu_user_ftrs = PPC_FEATURE_HAS_MMU },
|
||||
{ .pabyte = 0, .pabit = 1, .cpu_user_ftrs = PPC_FEATURE_HAS_FPU },
|
||||
{ .pabyte = 0, .pabit = 3, .cpu_features = CPU_FTR_CTRL },
|
||||
{ .pabyte = 0, .pabit = 6, .cpu_features = CPU_FTR_NOEXECUTE },
|
||||
{ .pabyte = 1, .pabit = 2, .mmu_features = MMU_FTR_CI_LARGE_PAGE },
|
||||
{ .pabyte = 40, .pabit = 0, .mmu_features = MMU_FTR_TYPE_RADIX },
|
||||
{ .pabyte = 1, .pabit = 1, .invert = 1, .cpu_features = CPU_FTR_NODSISRALIGN },
|
||||
{ .pabyte = 5, .pabit = 0, .cpu_features = CPU_FTR_REAL_LE,
|
||||
.cpu_user_ftrs = PPC_FEATURE_TRUE_LE },
|
||||
/*
|
||||
* If the kernel doesn't support TM (ie CONFIG_PPC_TRANSACTIONAL_MEM=n),
|
||||
* we don't want to turn on TM here, so we use the *_COMP versions
|
||||
* which are 0 if the kernel doesn't support TM.
|
||||
*/
|
||||
{CPU_FTR_TM_COMP, 0, 0,
|
||||
PPC_FEATURE2_HTM_COMP|PPC_FEATURE2_HTM_NOSC_COMP, 22, 0, 0},
|
||||
{0, MMU_FTR_TYPE_RADIX, 0, 0, 40, 0, 0},
|
||||
{ .pabyte = 22, .pabit = 0, .cpu_features = CPU_FTR_TM_COMP,
|
||||
.cpu_user_ftrs2 = PPC_FEATURE2_HTM_COMP | PPC_FEATURE2_HTM_NOSC_COMP },
|
||||
};
|
||||
|
||||
static void __init scan_features(unsigned long node, const unsigned char *ftrs,
|
||||
@ -427,7 +428,7 @@ static int __init early_init_dt_scan_chosen_ppc(unsigned long node,
|
||||
tce_alloc_end = *lprop;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KEXEC
|
||||
#ifdef CONFIG_KEXEC_CORE
|
||||
lprop = of_get_flat_dt_prop(node, "linux,crashkernel-base", NULL);
|
||||
if (lprop)
|
||||
crashk_res.start = *lprop;
|
||||
|
@ -461,14 +461,14 @@ static int __init prom_next_node(phandle *nodep)
|
||||
}
|
||||
}
|
||||
|
||||
static int inline prom_getprop(phandle node, const char *pname,
|
||||
static inline int prom_getprop(phandle node, const char *pname,
|
||||
void *value, size_t valuelen)
|
||||
{
|
||||
return call_prom("getprop", 4, 1, node, ADDR(pname),
|
||||
(u32)(unsigned long) value, (u32) valuelen);
|
||||
}
|
||||
|
||||
static int inline prom_getproplen(phandle node, const char *pname)
|
||||
static inline int prom_getproplen(phandle node, const char *pname)
|
||||
{
|
||||
return call_prom("getproplen", 2, 1, node, ADDR(pname));
|
||||
}
|
||||
@ -635,13 +635,7 @@ static void __init early_cmdline_parse(void)
|
||||
*
|
||||
* See prom.h for the definition of the bits specified in the
|
||||
* architecture vector.
|
||||
*
|
||||
* Because the description vector contains a mix of byte and word
|
||||
* values, we declare it as an unsigned char array, and use this
|
||||
* macro to put word values in.
|
||||
*/
|
||||
#define W(x) ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
|
||||
((x) >> 8) & 0xff, (x) & 0xff
|
||||
|
||||
/* Firmware expects the value to be n - 1, where n is the # of vectors */
|
||||
#define NUM_VECTORS(n) ((n) - 1)
|
||||
@ -652,92 +646,205 @@ static void __init early_cmdline_parse(void)
|
||||
*/
|
||||
#define VECTOR_LENGTH(n) (1 + (n) - 2)
|
||||
|
||||
unsigned char ibm_architecture_vec[] = {
|
||||
W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */
|
||||
W(0xffff0000), W(0x003e0000), /* POWER6 */
|
||||
W(0xffff0000), W(0x003f0000), /* POWER7 */
|
||||
W(0xffff0000), W(0x004b0000), /* POWER8E */
|
||||
W(0xffff0000), W(0x004c0000), /* POWER8NVL */
|
||||
W(0xffff0000), W(0x004d0000), /* POWER8 */
|
||||
W(0xffffffff), W(0x0f000004), /* all 2.07-compliant */
|
||||
W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */
|
||||
W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */
|
||||
W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */
|
||||
NUM_VECTORS(6), /* 6 option vectors */
|
||||
struct option_vector1 {
|
||||
u8 byte1;
|
||||
u8 arch_versions;
|
||||
} __packed;
|
||||
|
||||
/* option vector 1: processor architectures supported */
|
||||
VECTOR_LENGTH(2), /* length */
|
||||
0, /* don't ignore, don't halt */
|
||||
OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
|
||||
OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
|
||||
struct option_vector2 {
|
||||
u8 byte1;
|
||||
__be16 reserved;
|
||||
__be32 real_base;
|
||||
__be32 real_size;
|
||||
__be32 virt_base;
|
||||
__be32 virt_size;
|
||||
__be32 load_base;
|
||||
__be32 min_rma;
|
||||
__be32 min_load;
|
||||
u8 min_rma_percent;
|
||||
u8 max_pft_size;
|
||||
} __packed;
|
||||
|
||||
struct option_vector3 {
|
||||
u8 byte1;
|
||||
u8 byte2;
|
||||
} __packed;
|
||||
|
||||
struct option_vector4 {
|
||||
u8 byte1;
|
||||
u8 min_vp_cap;
|
||||
} __packed;
|
||||
|
||||
struct option_vector5 {
|
||||
u8 byte1;
|
||||
u8 byte2;
|
||||
u8 byte3;
|
||||
u8 cmo;
|
||||
u8 associativity;
|
||||
u8 bin_opts;
|
||||
u8 micro_checkpoint;
|
||||
u8 reserved0;
|
||||
__be32 max_cpus;
|
||||
__be16 papr_level;
|
||||
__be16 reserved1;
|
||||
u8 platform_facilities;
|
||||
u8 reserved2;
|
||||
__be16 reserved3;
|
||||
u8 subprocessors;
|
||||
} __packed;
|
||||
|
||||
struct option_vector6 {
|
||||
u8 reserved;
|
||||
u8 secondary_pteg;
|
||||
u8 os_name;
|
||||
} __packed;
|
||||
|
||||
struct ibm_arch_vec {
|
||||
struct { u32 mask, val; } pvrs[10];
|
||||
|
||||
u8 num_vectors;
|
||||
|
||||
u8 vec1_len;
|
||||
struct option_vector1 vec1;
|
||||
|
||||
u8 vec2_len;
|
||||
struct option_vector2 vec2;
|
||||
|
||||
u8 vec3_len;
|
||||
struct option_vector3 vec3;
|
||||
|
||||
u8 vec4_len;
|
||||
struct option_vector4 vec4;
|
||||
|
||||
u8 vec5_len;
|
||||
struct option_vector5 vec5;
|
||||
|
||||
u8 vec6_len;
|
||||
struct option_vector6 vec6;
|
||||
} __packed;
|
||||
|
||||
struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = {
|
||||
.pvrs = {
|
||||
{
|
||||
.mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */
|
||||
.val = cpu_to_be32(0x003a0000),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xffff0000), /* POWER6 */
|
||||
.val = cpu_to_be32(0x003e0000),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xffff0000), /* POWER7 */
|
||||
.val = cpu_to_be32(0x003f0000),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xffff0000), /* POWER8E */
|
||||
.val = cpu_to_be32(0x004b0000),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xffff0000), /* POWER8NVL */
|
||||
.val = cpu_to_be32(0x004c0000),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xffff0000), /* POWER8 */
|
||||
.val = cpu_to_be32(0x004d0000),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xffffffff), /* all 2.07-compliant */
|
||||
.val = cpu_to_be32(0x0f000004),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xffffffff), /* all 2.06-compliant */
|
||||
.val = cpu_to_be32(0x0f000003),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xffffffff), /* all 2.05-compliant */
|
||||
.val = cpu_to_be32(0x0f000002),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xfffffffe), /* all 2.04-compliant and earlier */
|
||||
.val = cpu_to_be32(0x0f000001),
|
||||
},
|
||||
},
|
||||
|
||||
.num_vectors = NUM_VECTORS(6),
|
||||
|
||||
.vec1_len = VECTOR_LENGTH(sizeof(struct option_vector1)),
|
||||
.vec1 = {
|
||||
.byte1 = 0,
|
||||
.arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
|
||||
OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
|
||||
},
|
||||
|
||||
.vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
|
||||
/* option vector 2: Open Firmware options supported */
|
||||
VECTOR_LENGTH(33), /* length */
|
||||
OV2_REAL_MODE,
|
||||
0, 0,
|
||||
W(0xffffffff), /* real_base */
|
||||
W(0xffffffff), /* real_size */
|
||||
W(0xffffffff), /* virt_base */
|
||||
W(0xffffffff), /* virt_size */
|
||||
W(0xffffffff), /* load_base */
|
||||
W(256), /* 256MB min RMA */
|
||||
W(0xffffffff), /* full client load */
|
||||
0, /* min RMA percentage of total RAM */
|
||||
48, /* max log_2(hash table size) */
|
||||
.vec2 = {
|
||||
.byte1 = OV2_REAL_MODE,
|
||||
.reserved = 0,
|
||||
.real_base = cpu_to_be32(0xffffffff),
|
||||
.real_size = cpu_to_be32(0xffffffff),
|
||||
.virt_base = cpu_to_be32(0xffffffff),
|
||||
.virt_size = cpu_to_be32(0xffffffff),
|
||||
.load_base = cpu_to_be32(0xffffffff),
|
||||
.min_rma = cpu_to_be32(256), /* 256MB min RMA */
|
||||
.min_load = cpu_to_be32(0xffffffff), /* full client load */
|
||||
.min_rma_percent = 0, /* min RMA percentage of total RAM */
|
||||
.max_pft_size = 48, /* max log_2(hash table size) */
|
||||
},
|
||||
|
||||
.vec3_len = VECTOR_LENGTH(sizeof(struct option_vector3)),
|
||||
/* option vector 3: processor options supported */
|
||||
VECTOR_LENGTH(2), /* length */
|
||||
0, /* don't ignore, don't halt */
|
||||
OV3_FP | OV3_VMX | OV3_DFP,
|
||||
.vec3 = {
|
||||
.byte1 = 0, /* don't ignore, don't halt */
|
||||
.byte2 = OV3_FP | OV3_VMX | OV3_DFP,
|
||||
},
|
||||
|
||||
.vec4_len = VECTOR_LENGTH(sizeof(struct option_vector4)),
|
||||
/* option vector 4: IBM PAPR implementation */
|
||||
VECTOR_LENGTH(2), /* length */
|
||||
0, /* don't halt */
|
||||
OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
|
||||
.vec4 = {
|
||||
.byte1 = 0, /* don't halt */
|
||||
.min_vp_cap = OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
|
||||
},
|
||||
|
||||
.vec5_len = VECTOR_LENGTH(sizeof(struct option_vector5)),
|
||||
/* option vector 5: PAPR/OF options */
|
||||
VECTOR_LENGTH(21), /* length */
|
||||
0, /* don't ignore, don't halt */
|
||||
OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
|
||||
OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
|
||||
.vec5 = {
|
||||
.byte1 = 0, /* don't ignore, don't halt */
|
||||
.byte2 = OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
|
||||
OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
/* PCIe/MSI support. Without MSI full PCIe is not supported */
|
||||
OV5_FEAT(OV5_MSI),
|
||||
/* PCIe/MSI support. Without MSI full PCIe is not supported */
|
||||
OV5_FEAT(OV5_MSI),
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif
|
||||
0,
|
||||
.byte3 = 0,
|
||||
.cmo =
|
||||
#ifdef CONFIG_PPC_SMLPAR
|
||||
OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
|
||||
OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif
|
||||
OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
/* WARNING: The offset of the "number of cores" field below
|
||||
* must match by the macro below. Update the definition if
|
||||
* the structure layout changes.
|
||||
*/
|
||||
#define IBM_ARCH_VEC_NRCORES_OFFSET 133
|
||||
W(NR_CPUS), /* number of cores supported */
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) |
|
||||
OV5_FEAT(OV5_PFO_HW_842), /* Byte 17 */
|
||||
0, /* Byte 18 */
|
||||
0, /* Byte 19 */
|
||||
0, /* Byte 20 */
|
||||
OV5_FEAT(OV5_SUB_PROCESSORS), /* Byte 21 */
|
||||
.associativity = OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
|
||||
.bin_opts = 0,
|
||||
.micro_checkpoint = 0,
|
||||
.reserved0 = 0,
|
||||
.max_cpus = cpu_to_be32(NR_CPUS), /* number of cores supported */
|
||||
.papr_level = 0,
|
||||
.reserved1 = 0,
|
||||
.platform_facilities = OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) | OV5_FEAT(OV5_PFO_HW_842),
|
||||
.reserved2 = 0,
|
||||
.reserved3 = 0,
|
||||
.subprocessors = 1,
|
||||
},
|
||||
|
||||
/* option vector 6: IBM PAPR hints */
|
||||
VECTOR_LENGTH(3), /* length */
|
||||
0,
|
||||
0,
|
||||
OV6_LINUX,
|
||||
.vec6_len = VECTOR_LENGTH(sizeof(struct option_vector6)),
|
||||
.vec6 = {
|
||||
.reserved = 0,
|
||||
.secondary_pteg = 0,
|
||||
.os_name = OV6_LINUX,
|
||||
},
|
||||
};
|
||||
|
||||
/* Old method - ELF header with PT_NOTE sections only works on BE */
|
||||
@ -873,7 +980,6 @@ static void __init prom_send_capabilities(void)
|
||||
ihandle root;
|
||||
prom_arg_t ret;
|
||||
u32 cores;
|
||||
unsigned char *ptcores;
|
||||
|
||||
root = call_prom("open", 1, 1, ADDR("/"));
|
||||
if (root != 0) {
|
||||
@ -884,37 +990,18 @@ static void __init prom_send_capabilities(void)
|
||||
* divide NR_CPUS.
|
||||
*/
|
||||
|
||||
/* The core value may start at an odd address. If such a word
|
||||
* access is made at a cache line boundary, this leads to an
|
||||
* exception which may not be handled at this time.
|
||||
* Forcing a per byte access to avoid exception.
|
||||
*/
|
||||
ptcores = &ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET];
|
||||
cores = 0;
|
||||
cores |= ptcores[0] << 24;
|
||||
cores |= ptcores[1] << 16;
|
||||
cores |= ptcores[2] << 8;
|
||||
cores |= ptcores[3];
|
||||
if (cores != NR_CPUS) {
|
||||
prom_printf("WARNING ! "
|
||||
"ibm_architecture_vec structure inconsistent: %lu!\n",
|
||||
cores);
|
||||
} else {
|
||||
cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
|
||||
prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n",
|
||||
cores, NR_CPUS);
|
||||
ptcores[0] = (cores >> 24) & 0xff;
|
||||
ptcores[1] = (cores >> 16) & 0xff;
|
||||
ptcores[2] = (cores >> 8) & 0xff;
|
||||
ptcores[3] = cores & 0xff;
|
||||
}
|
||||
cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
|
||||
prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n",
|
||||
cores, NR_CPUS);
|
||||
|
||||
ibm_architecture_vec.vec5.max_cpus = cpu_to_be32(cores);
|
||||
|
||||
/* try calling the ibm,client-architecture-support method */
|
||||
prom_printf("Calling ibm,client-architecture-support...");
|
||||
if (call_prom_ret("call-method", 3, 2, &ret,
|
||||
ADDR("ibm,client-architecture-support"),
|
||||
root,
|
||||
ADDR(ibm_architecture_vec)) == 0) {
|
||||
ADDR(&ibm_architecture_vec)) == 0) {
|
||||
/* the call exists... */
|
||||
if (ret)
|
||||
prom_printf("\nWARNING: ibm,client-architecture"
|
||||
|
@ -915,7 +915,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
init_mm.context.pte_frag = NULL;
|
||||
#endif
|
||||
#ifdef CONFIG_SPAPR_TCE_IOMMU
|
||||
mm_iommu_init(&init_mm.context);
|
||||
mm_iommu_init(&init_mm);
|
||||
#endif
|
||||
irqstack_early_init();
|
||||
exc_lvl_early_init();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user