powerpc updates for 5.18
- Enforce kernel RO, and implement STRICT_MODULE_RWX for 603. - Add support for livepatch to 32-bit. - Implement CONFIG_DYNAMIC_FTRACE_WITH_ARGS. - Merge vdso64 and vdso32 into a single directory. - Fix build errors with newer binutils. - Add support for UADDR64 relocations, which are emitted by some toolchains. This allows powerpc to build with the latest lld. - Fix (another) potential userspace r13 corruption in transactional memory handling. - Cleanups of function descriptor handling & related fixes to LKDTM. Thanks to: Abdul Haleem, Alexey Kardashevskiy, Anders Roxell, Aneesh Kumar K.V, Anton Blanchard, Arnd Bergmann, Athira Rajeev, Bhaskar Chowdhury, Cédric Le Goater, Chen Jingwen, Christophe JAILLET, Christophe Leroy, Corentin Labbe, Daniel Axtens, Daniel Henrique Barboza, David Dai, Fabiano Rosas, Ganesh Goudar, Guo Zhengkui, Hangyu Hua, Haren Myneni, Hari Bathini, Igor Zhbanov, Jakob Koschel, Jason Wang, Jeremy Kerr, Joachim Wiberg, Jordan Niethe, Julia Lawall, Kajol Jain, Kees Cook, Laurent Dufour, Madhavan Srinivasan, Mamatha Inamdar, Maxime Bizon, Maxim Kiselev, Maxim Kochetkov, Michal Suchanek, Nageswara R Sastry, Nathan Lynch, Naveen N. Rao, Nicholas Piggin, Nour-eddine Taleb, Paul Menzel, Ping Fang, Pratik R. Sampat, Randy Dunlap, Ritesh Harjani, Rohan McLure, Russell Currey, Sachin Sant, Segher Boessenkool, Shivaprasad G Bhat, Sourabh Jain, Thierry Reding, Tobias Waldekranz, Tyrel Datwyler, Vaibhav Jain, Vladimir Oltean, Wedson Almeida Filho, YueHaibing. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEJFGtCPCthwEv2Y/bUevqPMjhpYAFAmI9TtQTHG1wZUBlbGxl cm1hbi5pZC5hdQAKCRBR6+o8yOGlgLp2D/0dwoliEJubRCfoawYUGhxTRZuo6ZYw EQzprOiFA/MtrZyPfbrX/FwxeeetzQWysaw2r5JAuQwx5Jb7Od9dNIrVmueFEktC hD4fkO8YT+QuOD3Xhp/rDQTImdw4fkeofIjnWIqEAtz0XGInmiRQKOnojVe/Po7f 72Yi1u80LxYBAnkN/Hhpmi/BsVmu0Nh3wELu+JZopQXjINj4RyD49ayCBSLbmiNc uo7oYzJ0/WsZHNTpX9kAzzCq+XmI3dKZPyf2AOCvoRxJTmUPCRZF9QCwsmQFikiI vZOdz4fI5e+C0aYJj8ODmWMrXiS+JUQdEShjGg9t9K6EN8idC8joKWpAuXjTA9KN kRjzXX7AvjxaMEGbLe8gjU0PmEjY3eSzMOy15Oc/C0DRRswXRzrXdx2AF+/J6bQb MWMM4aCKfcYs5/TENkEnV0xpbOCOy4ikHM1KZbxvVrShvjSlNIL9XTOnl/pNK5BJ XSSI2mfnjKkbI1+l0KQ4NBXIRTo6HLpu5jwY3Xh97Tq7kaEfqDbO5p2P2HoOCiLa ZjdzmpP99zM6wnqUSj+lyvjob7btyhoq6TKmPtxfKbR6OaSfRJ760BCJ5y15Y9Hc rHey4Y/NL7LqsVYFZxi4/T6Ncq1hNeYr2Fiis4gH+/1zjr6Cd4othnvw3Slaxhst AaHpN3pyx1QI6g== =8r2c -----END PGP SIGNATURE----- Merge tag 'powerpc-5.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux Pull powerpc updates from Michael Ellerman: "Livepatch support for 32-bit is probably the standout new feature, otherwise mostly just lots of bits and pieces all over the board. There's a series of commits cleaning up function descriptor handling, which touches a few other arches as well as LKDTM. It has acks from Arnd, Kees and Helge. Summary: - Enforce kernel RO, and implement STRICT_MODULE_RWX for 603. - Add support for livepatch to 32-bit. - Implement CONFIG_DYNAMIC_FTRACE_WITH_ARGS. - Merge vdso64 and vdso32 into a single directory. - Fix build errors with newer binutils. - Add support for UADDR64 relocations, which are emitted by some toolchains. This allows powerpc to build with the latest lld. - Fix (another) potential userspace r13 corruption in transactional memory handling. - Cleanups of function descriptor handling & related fixes to LKDTM. Thanks to Abdul Haleem, Alexey Kardashevskiy, Anders Roxell, Aneesh Kumar K.V, Anton Blanchard, Arnd Bergmann, Athira Rajeev, Bhaskar Chowdhury, Cédric Le Goater, Chen Jingwen, Christophe JAILLET, Christophe Leroy, Corentin Labbe, Daniel Axtens, Daniel Henrique Barboza, David Dai, Fabiano Rosas, Ganesh Goudar, Guo Zhengkui, Hangyu Hua, Haren Myneni, Hari Bathini, Igor Zhbanov, Jakob Koschel, Jason Wang, Jeremy Kerr, Joachim Wiberg, Jordan Niethe, Julia Lawall, Kajol Jain, Kees Cook, Laurent Dufour, Madhavan Srinivasan, Mamatha Inamdar, Maxime Bizon, Maxim Kiselev, Maxim Kochetkov, Michal Suchanek, Nageswara R Sastry, Nathan Lynch, Naveen N. Rao, Nicholas Piggin, Nour-eddine Taleb, Paul Menzel, Ping Fang, Pratik R. Sampat, Randy Dunlap, Ritesh Harjani, Rohan McLure, Russell Currey, Sachin Sant, Segher Boessenkool, Shivaprasad G Bhat, Sourabh Jain, Thierry Reding, Tobias Waldekranz, Tyrel Datwyler, Vaibhav Jain, Vladimir Oltean, Wedson Almeida Filho, and YueHaibing" * tag 'powerpc-5.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (179 commits) powerpc/pseries: Fix use after free in remove_phb_dynamic() powerpc/time: improve decrementer clockevent processing powerpc/time: Fix KVM host re-arming a timer beyond decrementer range powerpc/tm: Fix more userspace r13 corruption powerpc/xive: fix return value of __setup handler powerpc/64: Add UADDR64 relocation support powerpc: 8xx: fix a return value error in mpc8xx_pic_init powerpc/ps3: remove unneeded semicolons powerpc/64: Force inlining of prevent_user_access() and set_kuap() powerpc/bitops: Force inlining of fls() powerpc: declare unmodified attribute_group usages const powerpc/spufs: Fix build warning when CONFIG_PROC_FS=n powerpc/secvar: fix refcount leak in format_show() powerpc/64e: Tie PPC_BOOK3E_64 to PPC_FSL_BOOK3E powerpc: Move C prototypes out of asm-prototypes.h powerpc/kexec: Declare kexec_paca static powerpc/smp: Declare current_set static powerpc: Cleanup asm-prototypes.c powerpc/ftrace: Use STK_GOT in ftrace_mprofile.S powerpc/ftrace: Regroup PPC64 specific operations in ftrace_mprofile.S ...
This commit is contained in:
commit
1f1c153e40
|
@ -61,3 +61,15 @@ Description:
|
|||
* "CchRHCnt" : Cache Read Hit Count
|
||||
* "CchWHCnt" : Cache Write Hit Count
|
||||
* "FastWCnt" : Fast Write Count
|
||||
|
||||
What: /sys/bus/nd/devices/nmemX/papr/health_bitmap_inject
|
||||
Date: Jan, 2022
|
||||
KernelVersion: v5.17
|
||||
Contact: linuxppc-dev <linuxppc-dev@lists.ozlabs.org>, nvdimm@lists.linux.dev,
|
||||
Description:
|
||||
(RO) Reports the health bitmap inject bitmap that is applied to
|
||||
bitmap received from PowerVM via the H_SCM_HEALTH. This is used
|
||||
to forcibly set specific bits returned from Hcall. These is then
|
||||
used to simulate various health or shutdown states for an nvdimm
|
||||
and are set by user-space tools like ndctl by issuing a PAPR DSM.
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
What: /sys/firmware/papr/energy_scale_info
|
||||
Date: February 2022
|
||||
Contact: Linux for PowerPC mailing list <linuxppc-dev@ozlabs.org>
|
||||
Description: Directory hosting a set of platform attributes like
|
||||
energy/frequency on Linux running as a PAPR guest.
|
||||
|
||||
Each file in a directory contains a platform
|
||||
attribute hierarchy pertaining to performance/
|
||||
energy-savings mode and processor frequency.
|
||||
|
||||
What: /sys/firmware/papr/energy_scale_info/<id>
|
||||
Date: February 2022
|
||||
Contact: Linux for PowerPC mailing list <linuxppc-dev@ozlabs.org>
|
||||
Description: Energy, frequency attributes directory for POWERVM servers
|
||||
|
||||
What: /sys/firmware/papr/energy_scale_info/<id>/desc
|
||||
Date: February 2022
|
||||
Contact: Linux for PowerPC mailing list <linuxppc-dev@ozlabs.org>
|
||||
Description: String description of the energy attribute of <id>
|
||||
|
||||
What: /sys/firmware/papr/energy_scale_info/<id>/value
|
||||
Date: February 2022
|
||||
Contact: Linux for PowerPC mailing list <linuxppc-dev@ozlabs.org>
|
||||
Description: Numeric value of the energy attribute of <id>
|
||||
|
||||
What: /sys/firmware/papr/energy_scale_info/<id>/value_desc
|
||||
Date: February 2022
|
||||
Contact: Linux for PowerPC mailing list <linuxppc-dev@ozlabs.org>
|
||||
Description: String value of the energy attribute of <id>
|
|
@ -202,6 +202,9 @@ config HAVE_FUNCTION_ERROR_INJECTION
|
|||
config HAVE_NMI
|
||||
bool
|
||||
|
||||
config HAVE_FUNCTION_DESCRIPTORS
|
||||
bool
|
||||
|
||||
config TRACE_IRQFLAGS_SUPPORT
|
||||
bool
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ config IA64
|
|||
select HAVE_SETUP_PER_CPU_AREA
|
||||
select TTY
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_FUNCTION_DESCRIPTORS
|
||||
select HAVE_VIRT_CPU_ACCOUNTING
|
||||
select HUGETLB_PAGE_SIZE_VARIABLE if HUGETLB_PAGE
|
||||
select VIRT_TO_BUS
|
||||
|
|
|
@ -226,7 +226,7 @@ struct got_entry {
|
|||
* Layout of the Function Descriptor
|
||||
*/
|
||||
struct fdesc {
|
||||
uint64_t ip;
|
||||
uint64_t addr;
|
||||
uint64_t gp;
|
||||
};
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
|
||||
#include <linux/elf.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
typedef struct fdesc func_desc_t;
|
||||
|
||||
#include <asm-generic/sections.h>
|
||||
|
||||
extern char __phys_per_cpu_start[];
|
||||
|
@ -27,25 +30,4 @@ extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_b
|
|||
extern char __start_unwind[], __end_unwind[];
|
||||
extern char __start_ivt_text[], __end_ivt_text[];
|
||||
|
||||
#define HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR 1
|
||||
|
||||
#undef dereference_function_descriptor
|
||||
static inline void *dereference_function_descriptor(void *ptr)
|
||||
{
|
||||
struct fdesc *desc = ptr;
|
||||
void *p;
|
||||
|
||||
if (!get_kernel_nofault(p, (void *)&desc->ip))
|
||||
ptr = p;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
#undef dereference_kernel_function_descriptor
|
||||
static inline void *dereference_kernel_function_descriptor(void *ptr)
|
||||
{
|
||||
if (ptr < (void *)__start_opd || ptr >= (void *)__end_opd)
|
||||
return ptr;
|
||||
return dereference_function_descriptor(ptr);
|
||||
}
|
||||
|
||||
#endif /* _ASM_IA64_SECTIONS_H */
|
||||
|
|
|
@ -602,15 +602,15 @@ get_fdesc (struct module *mod, uint64_t value, int *okp)
|
|||
return value;
|
||||
|
||||
/* Look for existing function descriptor. */
|
||||
while (fdesc->ip) {
|
||||
if (fdesc->ip == value)
|
||||
while (fdesc->addr) {
|
||||
if (fdesc->addr == value)
|
||||
return (uint64_t)fdesc;
|
||||
if ((uint64_t) ++fdesc >= mod->arch.opd->sh_addr + mod->arch.opd->sh_size)
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Create new one */
|
||||
fdesc->ip = value;
|
||||
fdesc->addr = value;
|
||||
fdesc->gp = mod->arch.gp;
|
||||
return (uint64_t) fdesc;
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ config PARISC
|
|||
select HAVE_DYNAMIC_FTRACE_WITH_REGS
|
||||
select HAVE_SOFTIRQ_ON_OWN_STACK if IRQSTACKS
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
select HAVE_FUNCTION_DESCRIPTORS if 64BIT
|
||||
|
||||
help
|
||||
The PA-RISC microprocessor is designed by Hewlett-Packard and used
|
||||
|
|
|
@ -2,20 +2,14 @@
|
|||
#ifndef _PARISC_SECTIONS_H
|
||||
#define _PARISC_SECTIONS_H
|
||||
|
||||
#ifdef CONFIG_HAVE_FUNCTION_DESCRIPTORS
|
||||
#include <asm/elf.h>
|
||||
typedef Elf64_Fdesc func_desc_t;
|
||||
#endif
|
||||
|
||||
/* nothing to see, move along */
|
||||
#include <asm-generic/sections.h>
|
||||
|
||||
extern char __alt_instructions[], __alt_instructions_end[];
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
|
||||
#define HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR 1
|
||||
|
||||
#undef dereference_function_descriptor
|
||||
void *dereference_function_descriptor(void *);
|
||||
|
||||
#undef dereference_kernel_function_descriptor
|
||||
void *dereference_kernel_function_descriptor(void *);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -263,27 +263,6 @@ __get_wchan(struct task_struct *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
void *dereference_function_descriptor(void *ptr)
|
||||
{
|
||||
Elf64_Fdesc *desc = ptr;
|
||||
void *p;
|
||||
|
||||
if (!get_kernel_nofault(p, (void *)&desc->addr))
|
||||
ptr = p;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *dereference_kernel_function_descriptor(void *ptr)
|
||||
{
|
||||
if (ptr < (void *)__start_opd ||
|
||||
ptr >= (void *)__end_opd)
|
||||
return ptr;
|
||||
|
||||
return dereference_function_descriptor(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline unsigned long brk_rnd(void)
|
||||
{
|
||||
return (get_random_int() & BRK_RND_MASK) << PAGE_SHIFT;
|
||||
|
|
|
@ -9,6 +9,10 @@ config 64BIT
|
|||
bool
|
||||
default y if PPC64
|
||||
|
||||
config LIVEPATCH_64
|
||||
def_bool PPC64
|
||||
depends on LIVEPATCH
|
||||
|
||||
config MMU
|
||||
bool
|
||||
default y
|
||||
|
@ -132,7 +136,7 @@ config PPC
|
|||
select ARCH_HAS_SET_MEMORY
|
||||
select ARCH_HAS_STRICT_KERNEL_RWX if (PPC_BOOK3S || PPC_8xx || 40x) && !HIBERNATION
|
||||
select ARCH_HAS_STRICT_KERNEL_RWX if FSL_BOOKE && !HIBERNATION && !RANDOMIZE_BASE
|
||||
select ARCH_HAS_STRICT_MODULE_RWX if ARCH_HAS_STRICT_KERNEL_RWX && !PPC_BOOK3S_32
|
||||
select ARCH_HAS_STRICT_MODULE_RWX if ARCH_HAS_STRICT_KERNEL_RWX
|
||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||
select ARCH_HAS_UACCESS_FLUSHCACHE
|
||||
select ARCH_HAS_UBSAN_SANITIZE_ALL
|
||||
|
@ -198,11 +202,13 @@ config PPC
|
|||
select HAVE_DEBUG_KMEMLEAK
|
||||
select HAVE_DEBUG_STACKOVERFLOW
|
||||
select HAVE_DYNAMIC_FTRACE
|
||||
select HAVE_DYNAMIC_FTRACE_WITH_ARGS if MPROFILE_KERNEL || PPC32
|
||||
select HAVE_DYNAMIC_FTRACE_WITH_REGS if MPROFILE_KERNEL || PPC32
|
||||
select HAVE_EBPF_JIT
|
||||
select HAVE_EFFICIENT_UNALIGNED_ACCESS if !(CPU_LITTLE_ENDIAN && POWER7_CPU)
|
||||
select HAVE_FAST_GUP
|
||||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
select HAVE_FUNCTION_DESCRIPTORS if PPC64 && !CPU_LITTLE_ENDIAN
|
||||
select HAVE_FUNCTION_ERROR_INJECTION
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_TRACER
|
||||
|
@ -222,7 +228,7 @@ config PPC
|
|||
select HAVE_KPROBES_ON_FTRACE
|
||||
select HAVE_KRETPROBES
|
||||
select HAVE_LD_DEAD_CODE_DATA_ELIMINATION
|
||||
select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS && PPC64
|
||||
select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS
|
||||
select HAVE_MOD_ARCH_SPECIFIC
|
||||
select HAVE_NMI if PERF_EVENTS || (PPC64 && PPC_BOOK3S)
|
||||
select HAVE_OPTPROBES
|
||||
|
|
|
@ -171,7 +171,7 @@ else
|
|||
CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,$(call cc-option,-mtune=power5))
|
||||
CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mcpu=power5,-mcpu=power4)
|
||||
endif
|
||||
else
|
||||
else ifdef CONFIG_PPC_BOOK3E_64
|
||||
CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=powerpc64
|
||||
endif
|
||||
|
||||
|
@ -213,7 +213,7 @@ CHECKFLAGS += -m$(BITS) -D__powerpc__ -D__powerpc$(BITS)__
|
|||
ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
CHECKFLAGS += -D__BIG_ENDIAN__
|
||||
else
|
||||
CHECKFLAGS += -D__LITTLE_ENDIAN__
|
||||
CHECKFLAGS += -D__LITTLE_ENDIAN__ -D_CALL_ELF=2
|
||||
endif
|
||||
|
||||
ifdef CONFIG_476FPE_ERR46
|
||||
|
@ -421,9 +421,9 @@ ifeq ($(KBUILD_EXTMOD),)
|
|||
prepare: vdso_prepare
|
||||
vdso_prepare: prepare0
|
||||
$(if $(CONFIG_VDSO32),$(Q)$(MAKE) \
|
||||
$(build)=arch/powerpc/kernel/vdso32 include/generated/vdso32-offsets.h)
|
||||
$(build)=arch/powerpc/kernel/vdso include/generated/vdso32-offsets.h)
|
||||
$(if $(CONFIG_PPC64),$(Q)$(MAKE) \
|
||||
$(build)=arch/powerpc/kernel/vdso64 include/generated/vdso64-offsets.h)
|
||||
$(build)=arch/powerpc/kernel/vdso include/generated/vdso64-offsets.h)
|
||||
endif
|
||||
|
||||
archprepare: checkbin
|
||||
|
|
|
@ -16,6 +16,7 @@ kernel-vmlinux.strip.c
|
|||
kernel-vmlinux.strip.gz
|
||||
mktree
|
||||
otheros.bld
|
||||
otheros-too-big.bld
|
||||
uImage
|
||||
cuImage.*
|
||||
dtbImage.*
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* T1040RDB-REV-A Device Tree Source
|
||||
*
|
||||
* Copyright 2014 - 2015 Freescale Semiconductor Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "t1040rdb.dts"
|
||||
|
||||
/ {
|
||||
model = "fsl,T1040RDB-REV-A";
|
||||
compatible = "fsl,T1040RDB-REV-A";
|
||||
};
|
||||
|
||||
&seville_port0 {
|
||||
label = "ETH5";
|
||||
};
|
||||
|
||||
&seville_port2 {
|
||||
label = "ETH7";
|
||||
};
|
||||
|
||||
&seville_port4 {
|
||||
label = "ETH9";
|
||||
};
|
||||
|
||||
&seville_port6 {
|
||||
label = "ETH11";
|
||||
};
|
|
@ -119,7 +119,7 @@
|
|||
managed = "in-band-status";
|
||||
phy-handle = <&phy_qsgmii_0>;
|
||||
phy-mode = "qsgmii";
|
||||
label = "ETH5";
|
||||
label = "ETH3";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -135,7 +135,7 @@
|
|||
managed = "in-band-status";
|
||||
phy-handle = <&phy_qsgmii_2>;
|
||||
phy-mode = "qsgmii";
|
||||
label = "ETH7";
|
||||
label = "ETH5";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -151,7 +151,7 @@
|
|||
managed = "in-band-status";
|
||||
phy-handle = <&phy_qsgmii_4>;
|
||||
phy-mode = "qsgmii";
|
||||
label = "ETH9";
|
||||
label = "ETH7";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -167,7 +167,7 @@
|
|||
managed = "in-band-status";
|
||||
phy-handle = <&phy_qsgmii_6>;
|
||||
phy-mode = "qsgmii";
|
||||
label = "ETH11";
|
||||
label = "ETH9";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
|
|
@ -139,12 +139,12 @@
|
|||
fman@400000 {
|
||||
ethernet@e6000 {
|
||||
phy-handle = <&phy_rgmii_0>;
|
||||
phy-connection-type = "rgmii";
|
||||
phy-connection-type = "rgmii-id";
|
||||
};
|
||||
|
||||
ethernet@e8000 {
|
||||
phy-handle = <&phy_rgmii_1>;
|
||||
phy-connection-type = "rgmii";
|
||||
phy-connection-type = "rgmii-id";
|
||||
};
|
||||
|
||||
mdio0: mdio@fc000 {
|
||||
|
|
|
@ -132,7 +132,7 @@
|
|||
reg = <0x68>;
|
||||
};
|
||||
|
||||
dtt@48 {
|
||||
dtt@34 {
|
||||
compatible = "maxim,max1237";
|
||||
reg = <0x34>;
|
||||
};
|
||||
|
|
|
@ -136,7 +136,7 @@
|
|||
reg = <0x68>;
|
||||
};
|
||||
|
||||
dtt@48 {
|
||||
dtt@34 {
|
||||
compatible = "maxim,max1237";
|
||||
reg = <0x34>;
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#define PPC_STLCX stringify_in_c(stdcx.)
|
||||
#define PPC_CNTLZL stringify_in_c(cntlzd)
|
||||
#define PPC_MTOCRF(FXM, RS) MTOCRF((FXM), RS)
|
||||
#define PPC_SRL stringify_in_c(srd)
|
||||
#define PPC_LR_STKOFF 16
|
||||
#define PPC_MIN_STKFRM 112
|
||||
|
||||
|
@ -54,6 +55,7 @@
|
|||
#define PPC_STLCX stringify_in_c(stwcx.)
|
||||
#define PPC_CNTLZL stringify_in_c(cntlzw)
|
||||
#define PPC_MTOCRF stringify_in_c(mtcrf)
|
||||
#define PPC_SRL stringify_in_c(srw)
|
||||
#define PPC_LR_STKOFF 4
|
||||
#define PPC_MIN_STKFRM 16
|
||||
|
||||
|
|
|
@ -19,22 +19,6 @@
|
|||
|
||||
#include <uapi/asm/ucontext.h>
|
||||
|
||||
/* SMP */
|
||||
extern struct task_struct *current_set[NR_CPUS];
|
||||
extern struct task_struct *secondary_current;
|
||||
void start_secondary(void *unused);
|
||||
|
||||
/* kexec */
|
||||
struct paca_struct;
|
||||
struct kimage;
|
||||
extern struct paca_struct kexec_paca;
|
||||
void kexec_copy_flush(struct kimage *image);
|
||||
|
||||
/* pseries hcall tracing */
|
||||
extern struct static_key hcall_tracepoint_key;
|
||||
void __trace_hcall_entry(unsigned long opcode, unsigned long *args);
|
||||
void __trace_hcall_exit(long opcode, long retval, unsigned long *retbuf);
|
||||
|
||||
/* Ultravisor */
|
||||
#if defined(CONFIG_PPC_POWERNV) || defined(CONFIG_PPC_SVM)
|
||||
long ucall_norets(unsigned long opcode, ...);
|
||||
|
@ -50,49 +34,12 @@ int64_t __opal_call(int64_t a0, int64_t a1, int64_t a2, int64_t a3,
|
|||
int64_t a4, int64_t a5, int64_t a6, int64_t a7,
|
||||
int64_t opcode, uint64_t msr);
|
||||
|
||||
/* VMX copying */
|
||||
int enter_vmx_usercopy(void);
|
||||
int exit_vmx_usercopy(void);
|
||||
int enter_vmx_ops(void);
|
||||
void *exit_vmx_ops(void *dest);
|
||||
|
||||
/* signals, syscalls and interrupts */
|
||||
long sys_swapcontext(struct ucontext __user *old_ctx,
|
||||
struct ucontext __user *new_ctx,
|
||||
long ctx_size);
|
||||
#ifdef CONFIG_PPC32
|
||||
long sys_debug_setcontext(struct ucontext __user *ctx,
|
||||
int ndbg, struct sig_dbg_op __user *dbg);
|
||||
int
|
||||
ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
|
||||
struct __kernel_old_timeval __user *tvp);
|
||||
unsigned long __init early_init(unsigned long dt_ptr);
|
||||
void __init machine_init(u64 dt_ptr);
|
||||
#endif
|
||||
long system_call_exception(long r3, long r4, long r5, long r6, long r7, long r8, unsigned long r0, struct pt_regs *regs);
|
||||
notrace unsigned long syscall_exit_prepare(unsigned long r3, struct pt_regs *regs, long scv);
|
||||
notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs);
|
||||
notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs);
|
||||
#ifdef CONFIG_PPC64
|
||||
unsigned long syscall_exit_restart(unsigned long r3, struct pt_regs *regs);
|
||||
unsigned long interrupt_exit_user_restart(struct pt_regs *regs);
|
||||
unsigned long interrupt_exit_kernel_restart(struct pt_regs *regs);
|
||||
#endif
|
||||
|
||||
long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low,
|
||||
u32 len_high, u32 len_low);
|
||||
long sys_switch_endian(void);
|
||||
|
||||
/* prom_init (OpenFirmware) */
|
||||
unsigned long __init prom_init(unsigned long r3, unsigned long r4,
|
||||
unsigned long pp,
|
||||
unsigned long r6, unsigned long r7,
|
||||
unsigned long kbase);
|
||||
|
||||
/* setup */
|
||||
void __init early_setup(unsigned long dt_ptr);
|
||||
void early_setup_secondary(void);
|
||||
|
||||
/* misc runtime */
|
||||
extern u64 __bswapdi2(u64);
|
||||
extern s64 __lshrdi3(s64, int);
|
||||
|
@ -103,11 +50,6 @@ extern int __ucmpdi2(u64, u64);
|
|||
|
||||
/* tracing */
|
||||
void _mcount(void);
|
||||
unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip,
|
||||
unsigned long sp);
|
||||
|
||||
void pnv_power9_force_smt4_catch(void);
|
||||
void pnv_power9_force_smt4_release(void);
|
||||
|
||||
/* Transaction memory related */
|
||||
void tm_enable(void);
|
||||
|
|
|
@ -287,7 +287,7 @@ static inline void arch___clear_bit_unlock(int nr, volatile unsigned long *addr)
|
|||
* fls: find last (most-significant) bit set.
|
||||
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
|
||||
*/
|
||||
static inline int fls(unsigned int x)
|
||||
static __always_inline int fls(unsigned int x)
|
||||
{
|
||||
int lz;
|
||||
|
||||
|
@ -305,7 +305,7 @@ static inline int fls(unsigned int x)
|
|||
* 32-bit fls calls.
|
||||
*/
|
||||
#ifdef CONFIG_PPC64
|
||||
static inline int fls64(__u64 x)
|
||||
static __always_inline int fls64(__u64 x)
|
||||
{
|
||||
int lz;
|
||||
|
||||
|
|
|
@ -298,28 +298,35 @@ static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, p
|
|||
unsigned long clr, unsigned long set, int huge)
|
||||
{
|
||||
pte_basic_t old;
|
||||
unsigned long tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
if (mmu_has_feature(MMU_FTR_HPTE_TABLE)) {
|
||||
unsigned long tmp;
|
||||
|
||||
asm volatile(
|
||||
#ifndef CONFIG_PTE_64BIT
|
||||
"1: lwarx %0, 0, %3\n"
|
||||
" andc %1, %0, %4\n"
|
||||
"1: lwarx %0, 0, %3\n"
|
||||
" andc %1, %0, %4\n"
|
||||
#else
|
||||
"1: lwarx %L0, 0, %3\n"
|
||||
" lwz %0, -4(%3)\n"
|
||||
" andc %1, %L0, %4\n"
|
||||
"1: lwarx %L0, 0, %3\n"
|
||||
" lwz %0, -4(%3)\n"
|
||||
" andc %1, %L0, %4\n"
|
||||
#endif
|
||||
" or %1, %1, %5\n"
|
||||
" stwcx. %1, 0, %3\n"
|
||||
" bne- 1b"
|
||||
: "=&r" (old), "=&r" (tmp), "=m" (*p)
|
||||
" or %1, %1, %5\n"
|
||||
" stwcx. %1, 0, %3\n"
|
||||
" bne- 1b"
|
||||
: "=&r" (old), "=&r" (tmp), "=m" (*p)
|
||||
#ifndef CONFIG_PTE_64BIT
|
||||
: "r" (p),
|
||||
: "r" (p),
|
||||
#else
|
||||
: "b" ((unsigned long)(p) + 4),
|
||||
: "b" ((unsigned long)(p) + 4),
|
||||
#endif
|
||||
"r" (clr), "r" (set), "m" (*p)
|
||||
: "cc" );
|
||||
"r" (clr), "r" (set), "m" (*p)
|
||||
: "cc" );
|
||||
} else {
|
||||
old = pte_val(*p);
|
||||
|
||||
*p = __pte((old & ~(pte_basic_t)clr) | set);
|
||||
}
|
||||
|
||||
return old;
|
||||
}
|
||||
|
|
|
@ -328,7 +328,7 @@ static inline unsigned long get_kuap(void)
|
|||
return mfspr(SPRN_AMR);
|
||||
}
|
||||
|
||||
static inline void set_kuap(unsigned long value)
|
||||
static __always_inline void set_kuap(unsigned long value)
|
||||
{
|
||||
if (!mmu_has_feature(MMU_FTR_BOOK3S_KUAP))
|
||||
return;
|
||||
|
@ -398,7 +398,7 @@ static __always_inline void allow_user_access(void __user *to, const void __user
|
|||
|
||||
#endif /* !CONFIG_PPC_KUAP */
|
||||
|
||||
static inline void prevent_user_access(unsigned long dir)
|
||||
static __always_inline void prevent_user_access(unsigned long dir)
|
||||
{
|
||||
set_kuap(AMR_KUAP_BLOCKED);
|
||||
if (static_branch_unlikely(&uaccess_flush_key))
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#ifdef __ASSEMBLY__
|
||||
#include <asm/asm-offsets.h>
|
||||
#ifdef CONFIG_DEBUG_BUGVERBOSE
|
||||
.macro EMIT_BUG_ENTRY addr,file,line,flags
|
||||
.macro __EMIT_BUG_ENTRY addr,file,line,flags
|
||||
.section __bug_table,"aw"
|
||||
5001: .4byte \addr - 5001b, 5002f - 5001b
|
||||
.short \line, \flags
|
||||
|
@ -22,7 +22,7 @@
|
|||
.previous
|
||||
.endm
|
||||
#else
|
||||
.macro EMIT_BUG_ENTRY addr,file,line,flags
|
||||
.macro __EMIT_BUG_ENTRY addr,file,line,flags
|
||||
.section __bug_table,"aw"
|
||||
5001: .4byte \addr - 5001b
|
||||
.short \flags
|
||||
|
@ -33,7 +33,14 @@
|
|||
|
||||
.macro EMIT_WARN_ENTRY addr,file,line,flags
|
||||
EX_TABLE(\addr,\addr+4)
|
||||
EMIT_BUG_ENTRY \addr,\file,\line,\flags
|
||||
__EMIT_BUG_ENTRY \addr,\file,\line,\flags
|
||||
.endm
|
||||
|
||||
.macro EMIT_BUG_ENTRY addr,file,line,flags
|
||||
.if \flags & 1 /* BUGFLAG_WARNING */
|
||||
.err /* Use EMIT_WARN_ENTRY for warnings */
|
||||
.endif
|
||||
__EMIT_BUG_ENTRY \addr,\file,\line,\flags
|
||||
.endm
|
||||
|
||||
#else /* !__ASSEMBLY__ */
|
||||
|
|
|
@ -118,7 +118,7 @@ static inline unsigned long ppc_function_entry(void *func)
|
|||
* function's descriptor. The first entry in the descriptor is the
|
||||
* address of the function text.
|
||||
*/
|
||||
return ((func_descr_t *)func)->entry;
|
||||
return ((struct func_desc *)func)->addr;
|
||||
#else
|
||||
return (unsigned long)func;
|
||||
#endif
|
||||
|
|
|
@ -176,4 +176,10 @@ do { \
|
|||
/* Relocate the kernel image to @final_address */
|
||||
void relocate(unsigned long final_address);
|
||||
|
||||
struct func_desc {
|
||||
unsigned long addr;
|
||||
unsigned long toc;
|
||||
unsigned long env;
|
||||
};
|
||||
|
||||
#endif /* _ASM_POWERPC_ELF_H */
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
* but the gcc inline assembly syntax does not allow us to specify registers
|
||||
* on the clobber list that are also on the input/output list. Therefore,
|
||||
* the lists of clobbered registers depends on the number of register
|
||||
* parmeters ("+r" and "=r") passed to the hypercall.
|
||||
* parameters ("+r" and "=r") passed to the hypercall.
|
||||
*
|
||||
* Each assembly block should use one of the HCALL_CLOBBERSx macros. As a
|
||||
* general rule, 'x' is the number of parameters passed to the assembly
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#define FW_FEATURE_STUFF_TCE ASM_CONST(0x0000008000000000)
|
||||
#define FW_FEATURE_RPT_INVALIDATE ASM_CONST(0x0000010000000000)
|
||||
#define FW_FEATURE_FORM2_AFFINITY ASM_CONST(0x0000020000000000)
|
||||
#define FW_FEATURE_ENERGY_SCALE_INFO ASM_CONST(0x0000040000000000)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
|
@ -74,7 +75,8 @@ enum {
|
|||
FW_FEATURE_HPT_RESIZE | FW_FEATURE_DRMEM_V2 |
|
||||
FW_FEATURE_DRC_INFO | FW_FEATURE_BLOCK_REMOVE |
|
||||
FW_FEATURE_PAPR_SCM | FW_FEATURE_ULTRAVISOR |
|
||||
FW_FEATURE_RPT_INVALIDATE | FW_FEATURE_FORM2_AFFINITY,
|
||||
FW_FEATURE_RPT_INVALIDATE | FW_FEATURE_FORM2_AFFINITY |
|
||||
FW_FEATURE_ENERGY_SCALE_INFO,
|
||||
FW_FEATURE_PSERIES_ALWAYS = 0,
|
||||
FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_ULTRAVISOR,
|
||||
FW_FEATURE_POWERNV_ALWAYS = 0,
|
||||
|
|
|
@ -10,44 +10,7 @@
|
|||
|
||||
#define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
/* Based off of objdump output from glibc */
|
||||
|
||||
#define MCOUNT_SAVE_FRAME \
|
||||
stwu r1,-48(r1); \
|
||||
stw r3, 12(r1); \
|
||||
stw r4, 16(r1); \
|
||||
stw r5, 20(r1); \
|
||||
stw r6, 24(r1); \
|
||||
mflr r3; \
|
||||
lwz r4, 52(r1); \
|
||||
mfcr r5; \
|
||||
stw r7, 28(r1); \
|
||||
stw r8, 32(r1); \
|
||||
stw r9, 36(r1); \
|
||||
stw r10,40(r1); \
|
||||
stw r3, 44(r1); \
|
||||
stw r5, 8(r1)
|
||||
|
||||
#define MCOUNT_RESTORE_FRAME \
|
||||
lwz r6, 8(r1); \
|
||||
lwz r0, 44(r1); \
|
||||
lwz r3, 12(r1); \
|
||||
mtctr r0; \
|
||||
lwz r4, 16(r1); \
|
||||
mtcr r6; \
|
||||
lwz r5, 20(r1); \
|
||||
lwz r6, 24(r1); \
|
||||
lwz r0, 52(r1); \
|
||||
lwz r7, 28(r1); \
|
||||
lwz r8, 32(r1); \
|
||||
mtlr r0; \
|
||||
lwz r9, 36(r1); \
|
||||
lwz r10,40(r1); \
|
||||
addi r1, r1, 48
|
||||
|
||||
#else /* !__ASSEMBLY__ */
|
||||
#ifndef __ASSEMBLY__
|
||||
extern void _mcount(void);
|
||||
|
||||
static inline unsigned long ftrace_call_adjust(unsigned long addr)
|
||||
|
@ -56,9 +19,36 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
|
|||
return addr;
|
||||
}
|
||||
|
||||
unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip,
|
||||
unsigned long sp);
|
||||
|
||||
struct dyn_arch_ftrace {
|
||||
struct module *mod;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
|
||||
struct ftrace_regs {
|
||||
struct pt_regs regs;
|
||||
};
|
||||
|
||||
static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs)
|
||||
{
|
||||
/* We clear regs.msr in ftrace_call */
|
||||
return fregs->regs.msr ? &fregs->regs : NULL;
|
||||
}
|
||||
|
||||
static __always_inline void ftrace_instruction_pointer_set(struct ftrace_regs *fregs,
|
||||
unsigned long ip)
|
||||
{
|
||||
regs_set_return_ip(&fregs->regs, ip);
|
||||
}
|
||||
|
||||
struct ftrace_ops;
|
||||
|
||||
#define ftrace_graph_func ftrace_graph_func
|
||||
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *op, struct ftrace_regs *fregs);
|
||||
#endif
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
extern bool hugetlb_disabled;
|
||||
|
||||
void __init hugetlbpage_init_default(void);
|
||||
void __init hugetlbpage_init_defaultsize(void);
|
||||
|
||||
int slice_is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
|
||||
unsigned long len);
|
||||
|
@ -76,6 +76,9 @@ static inline void __init gigantic_hugetlb_cma_reserve(void)
|
|||
{
|
||||
}
|
||||
|
||||
static inline void __init hugetlbpage_init_defaultsize(void)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_HUGETLB_PAGE */
|
||||
|
||||
#endif /* _ASM_POWERPC_HUGETLB_H */
|
||||
|
|
|
@ -323,7 +323,8 @@
|
|||
#define H_SCM_PERFORMANCE_STATS 0x418
|
||||
#define H_RPT_INVALIDATE 0x448
|
||||
#define H_SCM_FLUSH 0x44C
|
||||
#define MAX_HCALL_OPCODE H_SCM_FLUSH
|
||||
#define H_GET_ENERGY_SCALE_INFO 0x450
|
||||
#define MAX_HCALL_OPCODE H_GET_ENERGY_SCALE_INFO
|
||||
|
||||
/* Scope args for H_SCM_UNBIND_ALL */
|
||||
#define H_UNBIND_SCOPE_ALL (0x1)
|
||||
|
@ -500,6 +501,11 @@ long plpar_hcall_raw(unsigned long opcode, unsigned long *retbuf, ...);
|
|||
long plpar_hcall9(unsigned long opcode, unsigned long *retbuf, ...);
|
||||
long plpar_hcall9_raw(unsigned long opcode, unsigned long *retbuf, ...);
|
||||
|
||||
/* pseries hcall tracing */
|
||||
extern struct static_key hcall_tracepoint_key;
|
||||
void __trace_hcall_entry(unsigned long opcode, unsigned long *args);
|
||||
void __trace_hcall_exit(long opcode, long retval, unsigned long *retbuf);
|
||||
|
||||
struct hvcall_mpp_data {
|
||||
unsigned long entitled_mem;
|
||||
unsigned long mapped_mem;
|
||||
|
|
|
@ -123,9 +123,6 @@ static inline void nap_adjust_return(struct pt_regs *regs)
|
|||
#endif
|
||||
}
|
||||
|
||||
struct interrupt_state {
|
||||
};
|
||||
|
||||
static inline void booke_restore_dbcr0(void)
|
||||
{
|
||||
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
|
||||
|
@ -138,7 +135,7 @@ static inline void booke_restore_dbcr0(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrupt_state *state)
|
||||
static inline void interrupt_enter_prepare(struct pt_regs *regs)
|
||||
{
|
||||
#ifdef CONFIG_PPC32
|
||||
if (!arch_irq_disabled_regs(regs))
|
||||
|
@ -228,17 +225,17 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrup
|
|||
* However interrupt_nmi_exit_prepare does return directly to regs, because
|
||||
* NMIs do not do "exit work" or replay soft-masked interrupts.
|
||||
*/
|
||||
static inline void interrupt_exit_prepare(struct pt_regs *regs, struct interrupt_state *state)
|
||||
static inline void interrupt_exit_prepare(struct pt_regs *regs)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void interrupt_async_enter_prepare(struct pt_regs *regs, struct interrupt_state *state)
|
||||
static inline void interrupt_async_enter_prepare(struct pt_regs *regs)
|
||||
{
|
||||
#ifdef CONFIG_PPC64
|
||||
/* Ensure interrupt_enter_prepare does not enable MSR[EE] */
|
||||
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
|
||||
#endif
|
||||
interrupt_enter_prepare(regs, state);
|
||||
interrupt_enter_prepare(regs);
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
/*
|
||||
* RI=1 is set by interrupt_enter_prepare, so this thread flags access
|
||||
|
@ -251,7 +248,7 @@ static inline void interrupt_async_enter_prepare(struct pt_regs *regs, struct in
|
|||
irq_enter();
|
||||
}
|
||||
|
||||
static inline void interrupt_async_exit_prepare(struct pt_regs *regs, struct interrupt_state *state)
|
||||
static inline void interrupt_async_exit_prepare(struct pt_regs *regs)
|
||||
{
|
||||
/*
|
||||
* Adjust at exit so the main handler sees the true NIA. This must
|
||||
|
@ -262,7 +259,7 @@ static inline void interrupt_async_exit_prepare(struct pt_regs *regs, struct int
|
|||
nap_adjust_return(regs);
|
||||
|
||||
irq_exit();
|
||||
interrupt_exit_prepare(regs, state);
|
||||
interrupt_exit_prepare(regs);
|
||||
}
|
||||
|
||||
struct interrupt_nmi_state {
|
||||
|
@ -447,13 +444,11 @@ static __always_inline void ____##func(struct pt_regs *regs); \
|
|||
\
|
||||
interrupt_handler void func(struct pt_regs *regs) \
|
||||
{ \
|
||||
struct interrupt_state state; \
|
||||
\
|
||||
interrupt_enter_prepare(regs, &state); \
|
||||
interrupt_enter_prepare(regs); \
|
||||
\
|
||||
____##func (regs); \
|
||||
\
|
||||
interrupt_exit_prepare(regs, &state); \
|
||||
interrupt_exit_prepare(regs); \
|
||||
} \
|
||||
NOKPROBE_SYMBOL(func); \
|
||||
\
|
||||
|
@ -482,14 +477,13 @@ static __always_inline long ____##func(struct pt_regs *regs); \
|
|||
\
|
||||
interrupt_handler long func(struct pt_regs *regs) \
|
||||
{ \
|
||||
struct interrupt_state state; \
|
||||
long ret; \
|
||||
\
|
||||
interrupt_enter_prepare(regs, &state); \
|
||||
interrupt_enter_prepare(regs); \
|
||||
\
|
||||
ret = ____##func (regs); \
|
||||
\
|
||||
interrupt_exit_prepare(regs, &state); \
|
||||
interrupt_exit_prepare(regs); \
|
||||
\
|
||||
return ret; \
|
||||
} \
|
||||
|
@ -518,13 +512,11 @@ static __always_inline void ____##func(struct pt_regs *regs); \
|
|||
\
|
||||
interrupt_handler void func(struct pt_regs *regs) \
|
||||
{ \
|
||||
struct interrupt_state state; \
|
||||
\
|
||||
interrupt_async_enter_prepare(regs, &state); \
|
||||
interrupt_async_enter_prepare(regs); \
|
||||
\
|
||||
____##func (regs); \
|
||||
\
|
||||
interrupt_async_exit_prepare(regs, &state); \
|
||||
interrupt_async_exit_prepare(regs); \
|
||||
} \
|
||||
NOKPROBE_SYMBOL(func); \
|
||||
\
|
||||
|
@ -612,7 +604,7 @@ DECLARE_INTERRUPT_HANDLER_RAW(do_slb_fault);
|
|||
DECLARE_INTERRUPT_HANDLER(do_bad_segment_interrupt);
|
||||
|
||||
/* hash_utils.c */
|
||||
DECLARE_INTERRUPT_HANDLER_RAW(do_hash_fault);
|
||||
DECLARE_INTERRUPT_HANDLER(do_hash_fault);
|
||||
|
||||
/* fault.c */
|
||||
DECLARE_INTERRUPT_HANDLER(do_page_fault);
|
||||
|
@ -644,6 +636,17 @@ static inline void interrupt_cond_local_irq_enable(struct pt_regs *regs)
|
|||
local_irq_enable();
|
||||
}
|
||||
|
||||
long system_call_exception(long r3, long r4, long r5, long r6, long r7, long r8,
|
||||
unsigned long r0, struct pt_regs *regs);
|
||||
notrace unsigned long syscall_exit_prepare(unsigned long r3, struct pt_regs *regs, long scv);
|
||||
notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs);
|
||||
notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs);
|
||||
#ifdef CONFIG_PPC64
|
||||
unsigned long syscall_exit_restart(unsigned long r3, struct pt_regs *regs);
|
||||
unsigned long interrupt_exit_user_restart(struct pt_regs *regs);
|
||||
unsigned long interrupt_exit_kernel_restart(struct pt_regs *regs);
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_INTERRUPT_H */
|
||||
|
|
|
@ -359,25 +359,37 @@ static inline void __raw_writeq_be(unsigned long v, volatile void __iomem *addr)
|
|||
*/
|
||||
static inline void __raw_rm_writeb(u8 val, volatile void __iomem *paddr)
|
||||
{
|
||||
__asm__ __volatile__("stbcix %0,0,%1"
|
||||
__asm__ __volatile__(".machine push; \
|
||||
.machine power6; \
|
||||
stbcix %0,0,%1; \
|
||||
.machine pop;"
|
||||
: : "r" (val), "r" (paddr) : "memory");
|
||||
}
|
||||
|
||||
static inline void __raw_rm_writew(u16 val, volatile void __iomem *paddr)
|
||||
{
|
||||
__asm__ __volatile__("sthcix %0,0,%1"
|
||||
__asm__ __volatile__(".machine push; \
|
||||
.machine power6; \
|
||||
sthcix %0,0,%1; \
|
||||
.machine pop;"
|
||||
: : "r" (val), "r" (paddr) : "memory");
|
||||
}
|
||||
|
||||
static inline void __raw_rm_writel(u32 val, volatile void __iomem *paddr)
|
||||
{
|
||||
__asm__ __volatile__("stwcix %0,0,%1"
|
||||
__asm__ __volatile__(".machine push; \
|
||||
.machine power6; \
|
||||
stwcix %0,0,%1; \
|
||||
.machine pop;"
|
||||
: : "r" (val), "r" (paddr) : "memory");
|
||||
}
|
||||
|
||||
static inline void __raw_rm_writeq(u64 val, volatile void __iomem *paddr)
|
||||
{
|
||||
__asm__ __volatile__("stdcix %0,0,%1"
|
||||
__asm__ __volatile__(".machine push; \
|
||||
.machine power6; \
|
||||
stdcix %0,0,%1; \
|
||||
.machine pop;"
|
||||
: : "r" (val), "r" (paddr) : "memory");
|
||||
}
|
||||
|
||||
|
@ -389,7 +401,10 @@ static inline void __raw_rm_writeq_be(u64 val, volatile void __iomem *paddr)
|
|||
static inline u8 __raw_rm_readb(volatile void __iomem *paddr)
|
||||
{
|
||||
u8 ret;
|
||||
__asm__ __volatile__("lbzcix %0,0, %1"
|
||||
__asm__ __volatile__(".machine push; \
|
||||
.machine power6; \
|
||||
lbzcix %0,0, %1; \
|
||||
.machine pop;"
|
||||
: "=r" (ret) : "r" (paddr) : "memory");
|
||||
return ret;
|
||||
}
|
||||
|
@ -397,7 +412,10 @@ static inline u8 __raw_rm_readb(volatile void __iomem *paddr)
|
|||
static inline u16 __raw_rm_readw(volatile void __iomem *paddr)
|
||||
{
|
||||
u16 ret;
|
||||
__asm__ __volatile__("lhzcix %0,0, %1"
|
||||
__asm__ __volatile__(".machine push; \
|
||||
.machine power6; \
|
||||
lhzcix %0,0, %1; \
|
||||
.machine pop;"
|
||||
: "=r" (ret) : "r" (paddr) : "memory");
|
||||
return ret;
|
||||
}
|
||||
|
@ -405,7 +423,10 @@ static inline u16 __raw_rm_readw(volatile void __iomem *paddr)
|
|||
static inline u32 __raw_rm_readl(volatile void __iomem *paddr)
|
||||
{
|
||||
u32 ret;
|
||||
__asm__ __volatile__("lwzcix %0,0, %1"
|
||||
__asm__ __volatile__(".machine push; \
|
||||
.machine power6; \
|
||||
lwzcix %0,0, %1; \
|
||||
.machine pop;"
|
||||
: "=r" (ret) : "r" (paddr) : "memory");
|
||||
return ret;
|
||||
}
|
||||
|
@ -413,7 +434,10 @@ static inline u32 __raw_rm_readl(volatile void __iomem *paddr)
|
|||
static inline u64 __raw_rm_readq(volatile void __iomem *paddr)
|
||||
{
|
||||
u64 ret;
|
||||
__asm__ __volatile__("ldcix %0,0, %1"
|
||||
__asm__ __volatile__(".machine push; \
|
||||
.machine power6; \
|
||||
ldcix %0,0, %1; \
|
||||
.machine pop;"
|
||||
: "=r" (ret) : "r" (paddr) : "memory");
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -96,6 +96,8 @@ static inline bool kdump_in_progress(void)
|
|||
void relocate_new_kernel(unsigned long indirection_page, unsigned long reboot_code_buffer,
|
||||
unsigned long start_address) __noreturn;
|
||||
|
||||
void kexec_copy_flush(struct kimage *image);
|
||||
|
||||
#ifdef CONFIG_KEXEC_FILE
|
||||
extern const struct kexec_file_ops kexec_elf64_ops;
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <asm/hvcall.h>
|
||||
#include <asm/mce.h>
|
||||
|
||||
#define __KVM_HAVE_ARCH_VCPU_DEBUGFS
|
||||
|
||||
#define KVM_MAX_VCPUS NR_CPUS
|
||||
#define KVM_MAX_VCORES NR_CPUS
|
||||
|
||||
|
@ -295,7 +297,6 @@ struct kvm_arch {
|
|||
bool dawr1_enabled;
|
||||
pgd_t *pgtable;
|
||||
u64 process_table;
|
||||
struct dentry *debugfs_dir;
|
||||
struct kvm_resize_hpt *resize_hpt; /* protected by kvm->lock */
|
||||
#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
|
||||
#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
|
||||
|
@ -673,7 +674,6 @@ struct kvm_vcpu_arch {
|
|||
u64 timing_min_duration[__NUMBER_OF_KVM_EXIT_TYPES];
|
||||
u64 timing_max_duration[__NUMBER_OF_KVM_EXIT_TYPES];
|
||||
u64 timing_last_exit;
|
||||
struct dentry *debugfs_exit_timing;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
|
@ -831,8 +831,6 @@ struct kvm_vcpu_arch {
|
|||
struct kvmhv_tb_accumulator rm_exit; /* real-mode exit code */
|
||||
struct kvmhv_tb_accumulator guest_time; /* guest execution */
|
||||
struct kvmhv_tb_accumulator cede_time; /* time napping inside guest */
|
||||
|
||||
struct dentry *debugfs_dir;
|
||||
#endif /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */
|
||||
};
|
||||
|
||||
|
|
|
@ -314,6 +314,8 @@ struct kvmppc_ops {
|
|||
int (*svm_off)(struct kvm *kvm);
|
||||
int (*enable_dawr1)(struct kvm *kvm);
|
||||
bool (*hash_v3_possible)(void);
|
||||
int (*create_vm_debugfs)(struct kvm *kvm);
|
||||
int (*create_vcpu_debugfs)(struct kvm_vcpu *vcpu, struct dentry *debugfs_dentry);
|
||||
};
|
||||
|
||||
extern struct kvmppc_ops *kvmppc_hv_ops;
|
||||
|
|
|
@ -14,21 +14,21 @@
|
|||
#ifdef CONFIG_LIVEPATCH
|
||||
static inline void klp_arch_set_pc(struct ftrace_regs *fregs, unsigned long ip)
|
||||
{
|
||||
struct pt_regs *regs = ftrace_get_regs(fregs);
|
||||
|
||||
regs_set_return_ip(regs, ip);
|
||||
ftrace_instruction_pointer_set(fregs, ip);
|
||||
}
|
||||
|
||||
#define klp_get_ftrace_location klp_get_ftrace_location
|
||||
static inline unsigned long klp_get_ftrace_location(unsigned long faddr)
|
||||
{
|
||||
/*
|
||||
* Live patch works only with -mprofile-kernel on PPC. In this case,
|
||||
* the ftrace location is always within the first 16 bytes.
|
||||
* Live patch works on PPC32 and only with -mprofile-kernel on PPC64. In
|
||||
* both cases, the ftrace location is always within the first 16 bytes.
|
||||
*/
|
||||
return ftrace_location_range(faddr, faddr + 16);
|
||||
}
|
||||
#endif /* CONFIG_LIVEPATCH */
|
||||
|
||||
#ifdef CONFIG_LIVEPATCH_64
|
||||
static inline void klp_init_thread_info(struct task_struct *p)
|
||||
{
|
||||
/* + 1 to account for STACK_END_MAGIC */
|
||||
|
@ -36,6 +36,6 @@ static inline void klp_init_thread_info(struct task_struct *p)
|
|||
}
|
||||
#else
|
||||
static inline void klp_init_thread_info(struct task_struct *p) { }
|
||||
#endif /* CONFIG_LIVEPATCH */
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_POWERPC_LIVEPATCH_H */
|
||||
|
|
|
@ -10,11 +10,6 @@
|
|||
|
||||
#include <asm/setup.h>
|
||||
|
||||
/* We export this macro for external modules like Alsa to know if
|
||||
* ppc_md.feature_call is implemented or not
|
||||
*/
|
||||
#define CONFIG_PPC_HAS_FEATURE_CALLS
|
||||
|
||||
struct pt_regs;
|
||||
struct pci_bus;
|
||||
struct device_node;
|
||||
|
@ -99,6 +94,8 @@ struct machdep_calls {
|
|||
/* Called during machine check exception to retrive fixup address. */
|
||||
bool (*mce_check_early_recovery)(struct pt_regs *regs);
|
||||
|
||||
void (*machine_check_log_err)(void);
|
||||
|
||||
/* Motherboard/chipset features. This is a kind of general purpose
|
||||
* hook used to control some machine specific features (like reset
|
||||
* lines, chip power control, etc...).
|
||||
|
@ -235,21 +232,6 @@ extern struct machdep_calls *machine_id;
|
|||
machine_id == &mach_##name; \
|
||||
})
|
||||
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
/*
|
||||
* Power macintoshes have either a CUDA, PMU or SMU controlling
|
||||
* system reset, power, NVRAM, RTC.
|
||||
*/
|
||||
typedef enum sys_ctrler_kind {
|
||||
SYS_CTRLER_UNKNOWN = 0,
|
||||
SYS_CTRLER_CUDA = 1,
|
||||
SYS_CTRLER_PMU = 2,
|
||||
SYS_CTRLER_SMU = 3,
|
||||
} sys_ctrler_t;
|
||||
extern sys_ctrler_t sys_ctrler;
|
||||
|
||||
#endif /* CONFIG_PPC_PMAC */
|
||||
|
||||
static inline void log_error(char *buf, unsigned int err_type, int fatal)
|
||||
{
|
||||
if (ppc_md.log_error)
|
||||
|
|
|
@ -235,8 +235,21 @@ extern void machine_check_print_event_info(struct machine_check_event *evt,
|
|||
unsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr);
|
||||
extern void mce_common_process_ue(struct pt_regs *regs,
|
||||
struct mce_error_info *mce_err);
|
||||
void mce_irq_work_queue(void);
|
||||
int mce_register_notifier(struct notifier_block *nb);
|
||||
int mce_unregister_notifier(struct notifier_block *nb);
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
void mce_run_irq_context_handlers(void);
|
||||
#else
|
||||
static inline void mce_run_irq_context_handlers(void) { };
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
void set_mce_pending_irq_work(void);
|
||||
void clear_mce_pending_irq_work(void);
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
void flush_and_reload_slb(void);
|
||||
void flush_erat(void);
|
||||
|
|
|
@ -338,9 +338,6 @@ static inline int pte_young(pte_t pte)
|
|||
return pte_val(pte) & _PAGE_ACCESSED;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_PTE_SAME
|
||||
#define pte_same(A,B) ((pte_val(A) ^ pte_val(B)) == 0)
|
||||
|
||||
/*
|
||||
* Note that on Book E processors, the pmd contains the kernel virtual
|
||||
* (lowmem) address of the pte page. The physical address is less useful
|
||||
|
|
|
@ -282,9 +282,6 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma,
|
|||
flush_tlb_page(vma, address);
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_PTE_SAME
|
||||
#define pte_same(A,B) ((pte_val(A) ^ pte_val(B)) == 0)
|
||||
|
||||
#define pte_ERROR(e) \
|
||||
pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
|
||||
#define pmd_ERROR(e) \
|
||||
|
|
|
@ -288,6 +288,7 @@ struct paca_struct {
|
|||
#endif
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
struct mce_info *mce_info;
|
||||
u8 mce_pending_irq_work;
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
} ____cacheline_aligned;
|
||||
|
||||
|
|
|
@ -401,5 +401,17 @@ extern u32 __iomem *uninorth_base;
|
|||
*/
|
||||
extern int pmac_get_uninorth_variant(void);
|
||||
|
||||
/*
|
||||
* Power macintoshes have either a CUDA, PMU or SMU controlling
|
||||
* system reset, power, NVRAM, RTC.
|
||||
*/
|
||||
typedef enum sys_ctrler_kind {
|
||||
SYS_CTRLER_UNKNOWN = 0,
|
||||
SYS_CTRLER_CUDA = 1,
|
||||
SYS_CTRLER_PMU = 2,
|
||||
SYS_CTRLER_SMU = 3,
|
||||
} sys_ctrler_t;
|
||||
extern sys_ctrler_t sys_ctrler;
|
||||
|
||||
#endif /* __ASM_POWERPC_PMAC_FEATURE_H */
|
||||
#endif /* __KERNEL__ */
|
||||
|
|
|
@ -262,6 +262,8 @@
|
|||
#define PPC_INST_MFSPR_PVR 0x7c1f42a6
|
||||
#define PPC_INST_MFSPR_PVR_MASK 0xfc1ffffe
|
||||
#define PPC_INST_MTMSRD 0x7c000164
|
||||
#define PPC_INST_PASTE 0x7c20070d
|
||||
#define PPC_INST_PASTE_MASK 0xfc2007ff
|
||||
#define PPC_INST_POPCNTB 0x7c0000f4
|
||||
#define PPC_INST_POPCNTB_MASK 0xfc0007fe
|
||||
#define PPC_INST_RFEBB 0x4c000124
|
||||
|
|
|
@ -203,12 +203,7 @@ GLUE(.,name):
|
|||
|
||||
#else /* 32-bit */
|
||||
|
||||
#define _ENTRY(n) \
|
||||
.globl n; \
|
||||
n:
|
||||
|
||||
#define _GLOBAL(n) \
|
||||
.stabs __stringify(n:F-1),N_FUN,0,0,n;\
|
||||
.globl n; \
|
||||
n:
|
||||
|
||||
|
@ -697,12 +692,6 @@ END_FTR_SECTION_NESTED(CPU_FTR_CELL_TB_BUG, CPU_FTR_CELL_TB_BUG, 96)
|
|||
#define evr30 30
|
||||
#define evr31 31
|
||||
|
||||
/* some stab codes */
|
||||
#define N_FUN 36
|
||||
#define N_RSYM 64
|
||||
#define N_SLINE 68
|
||||
#define N_SO 100
|
||||
|
||||
#define RFSCV .long 0x4c0000a4
|
||||
|
||||
/*
|
||||
|
|
|
@ -411,6 +411,8 @@ extern int powersave_nap; /* set if nap mode can be used in idle loop */
|
|||
extern void power7_idle_type(unsigned long type);
|
||||
extern void arch300_idle_type(unsigned long stop_psscr_val,
|
||||
unsigned long stop_psscr_mask);
|
||||
void pnv_power9_force_smt4_catch(void);
|
||||
void pnv_power9_force_smt4_release(void);
|
||||
|
||||
extern int fix_alignment(struct pt_regs *);
|
||||
|
||||
|
@ -427,6 +429,12 @@ extern int fix_alignment(struct pt_regs *);
|
|||
|
||||
int do_mathemu(struct pt_regs *regs);
|
||||
|
||||
/* VMX copying */
|
||||
int enter_vmx_usercopy(void);
|
||||
int exit_vmx_usercopy(void);
|
||||
int enter_vmx_ops(void);
|
||||
void *exit_vmx_ops(void *dest);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* _ASM_POWERPC_PROCESSOR_H */
|
||||
|
|
|
@ -274,7 +274,6 @@ extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal);
|
|||
#ifdef CONFIG_PPC_PSERIES
|
||||
extern time64_t last_rtas_event;
|
||||
extern int clobbering_unread_rtas_event(void);
|
||||
extern int pseries_devicetree_update(s32 scope);
|
||||
extern void post_mobility_fixup(void);
|
||||
int rtas_syscall_dispatch_ibm_suspend_me(u64 handle);
|
||||
#else
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
#include <linux/elf.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#ifdef CONFIG_HAVE_FUNCTION_DESCRIPTORS
|
||||
typedef struct func_desc func_desc_t;
|
||||
#endif
|
||||
|
||||
#include <asm-generic/sections.h>
|
||||
|
||||
extern char __head_end[];
|
||||
|
@ -54,31 +58,6 @@ static inline int overlaps_kernel_text(unsigned long start, unsigned long end)
|
|||
(unsigned long)_stext < end;
|
||||
}
|
||||
|
||||
#ifdef PPC64_ELF_ABI_v1
|
||||
|
||||
#define HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR 1
|
||||
|
||||
#undef dereference_function_descriptor
|
||||
static inline void *dereference_function_descriptor(void *ptr)
|
||||
{
|
||||
struct ppc64_opd_entry *desc = ptr;
|
||||
void *p;
|
||||
|
||||
if (!get_kernel_nofault(p, (void *)&desc->funcaddr))
|
||||
ptr = p;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
#undef dereference_kernel_function_descriptor
|
||||
static inline void *dereference_kernel_function_descriptor(void *ptr)
|
||||
{
|
||||
if (ptr < (void *)__start_opd || ptr >= (void *)__end_opd)
|
||||
return ptr;
|
||||
|
||||
return dereference_function_descriptor(ptr);
|
||||
}
|
||||
#endif /* PPC64_ELF_ABI_v1 */
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#define SET_MEMORY_RW 1
|
||||
#define SET_MEMORY_NX 2
|
||||
#define SET_MEMORY_X 3
|
||||
#define SET_MEMORY_NP 4 /* Set memory non present */
|
||||
#define SET_MEMORY_P 5 /* Set memory present */
|
||||
|
||||
int change_memory_attr(unsigned long addr, int numpages, long action);
|
||||
|
||||
|
@ -29,6 +31,14 @@ static inline int set_memory_x(unsigned long addr, int numpages)
|
|||
return change_memory_attr(addr, numpages, SET_MEMORY_X);
|
||||
}
|
||||
|
||||
int set_memory_attr(unsigned long addr, int numpages, pgprot_t prot);
|
||||
static inline int set_memory_np(unsigned long addr, int numpages)
|
||||
{
|
||||
return change_memory_attr(addr, numpages, SET_MEMORY_NP);
|
||||
}
|
||||
|
||||
static inline int set_memory_p(unsigned long addr, int numpages)
|
||||
{
|
||||
return change_memory_attr(addr, numpages, SET_MEMORY_P);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -76,6 +76,13 @@ static inline void setup_spectre_v2(void) {}
|
|||
#endif
|
||||
void __init do_btb_flush_fixups(void);
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
unsigned long __init early_init(unsigned long dt_ptr);
|
||||
void __init machine_init(u64 dt_ptr);
|
||||
#endif
|
||||
void __init early_setup(unsigned long dt_ptr);
|
||||
void early_setup_secondary(void);
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_SETUP_H */
|
||||
|
|
|
@ -60,6 +60,9 @@ struct smp_ops_t {
|
|||
#endif
|
||||
};
|
||||
|
||||
extern struct task_struct *secondary_current;
|
||||
|
||||
void start_secondary(void *unused);
|
||||
extern int smp_send_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us);
|
||||
extern int smp_send_safe_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us);
|
||||
extern void smp_send_debugger_break(void);
|
||||
|
|
|
@ -249,8 +249,8 @@ void unregister_spu_syscalls(struct spufs_calls *calls);
|
|||
int spu_add_dev_attr(struct device_attribute *attr);
|
||||
void spu_remove_dev_attr(struct device_attribute *attr);
|
||||
|
||||
int spu_add_dev_attr_group(struct attribute_group *attrs);
|
||||
void spu_remove_dev_attr_group(struct attribute_group *attrs);
|
||||
int spu_add_dev_attr_group(const struct attribute_group *attrs);
|
||||
void spu_remove_dev_attr_group(const struct attribute_group *attrs);
|
||||
|
||||
extern void notify_spus_active(void);
|
||||
extern void do_notify_spus_active(void);
|
||||
|
|
|
@ -18,6 +18,10 @@ asmlinkage long sys_mmap2(unsigned long addr, size_t len,
|
|||
unsigned long fd, unsigned long pgoff);
|
||||
asmlinkage long ppc64_personality(unsigned long personality);
|
||||
asmlinkage long sys_rtas(struct rtas_args __user *uargs);
|
||||
int ppc_select(int n, fd_set __user *inp, fd_set __user *outp,
|
||||
fd_set __user *exp, struct __kernel_old_timeval __user *tvp);
|
||||
long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low,
|
||||
u32 len_high, u32 len_low);
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
unsigned long compat_sys_mmap2(unsigned long addr, size_t len,
|
||||
|
|
|
@ -51,7 +51,7 @@ struct thread_info {
|
|||
unsigned int cpu;
|
||||
#endif
|
||||
unsigned long local_flags; /* private flags for thread */
|
||||
#ifdef CONFIG_LIVEPATCH
|
||||
#ifdef CONFIG_LIVEPATCH_64
|
||||
unsigned long *livepatch_sp;
|
||||
#endif
|
||||
#if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC32)
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
|
||||
#ifdef __powerpc64__
|
||||
#if defined(_CALL_ELF) && _CALL_ELF == 2
|
||||
#define PPC64_ELF_ABI_v2
|
||||
#define PPC64_ELF_ABI_v2 1
|
||||
#else
|
||||
#define PPC64_ELF_ABI_v1
|
||||
#define PPC64_ELF_ABI_v1 1
|
||||
#endif
|
||||
#endif /* __powerpc64__ */
|
||||
|
||||
|
@ -23,12 +23,6 @@
|
|||
|
||||
typedef __vector128 vector128;
|
||||
|
||||
typedef struct {
|
||||
unsigned long entry;
|
||||
unsigned long toc;
|
||||
unsigned long env;
|
||||
} func_descr_t;
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_TYPES_H */
|
||||
|
|
|
@ -116,8 +116,11 @@ do { \
|
|||
*/
|
||||
#define __get_user_atomic_128_aligned(kaddr, uaddr, err) \
|
||||
__asm__ __volatile__( \
|
||||
".machine push\n" \
|
||||
".machine altivec\n" \
|
||||
"1: lvx 0,0,%1 # get user\n" \
|
||||
" stvx 0,0,%2 # put kernel\n" \
|
||||
".machine pop\n" \
|
||||
"2:\n" \
|
||||
".section .fixup,\"ax\"\n" \
|
||||
"3: li %0,%3\n" \
|
||||
|
|
|
@ -29,6 +29,16 @@
|
|||
#define VAS_THRESH_FIFO_GT_QTR_FULL 2
|
||||
#define VAS_THRESH_FIFO_GT_EIGHTH_FULL 3
|
||||
|
||||
/*
|
||||
* VAS window Linux status bits
|
||||
*/
|
||||
#define VAS_WIN_ACTIVE 0x0 /* Used in platform independent */
|
||||
/* vas mmap() */
|
||||
/* Window is closed in the hypervisor due to lost credit */
|
||||
#define VAS_WIN_NO_CRED_CLOSE 0x00000001
|
||||
/* Window is closed due to migration */
|
||||
#define VAS_WIN_MIGRATE_CLOSE 0x00000002
|
||||
|
||||
/*
|
||||
* Get/Set bit fields
|
||||
*/
|
||||
|
@ -59,6 +69,9 @@ struct vas_user_win_ref {
|
|||
struct pid *pid; /* PID of owner */
|
||||
struct pid *tgid; /* Thread group ID of owner */
|
||||
struct mm_struct *mm; /* Linux process mm_struct */
|
||||
struct mutex mmap_mutex; /* protects paste address mmap() */
|
||||
/* with DLPAR close/open windows */
|
||||
struct vm_area_struct *vma; /* Save VMA and used in DLPAR ops */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -67,6 +80,7 @@ struct vas_user_win_ref {
|
|||
struct vas_window {
|
||||
u32 winid;
|
||||
u32 wcreds_max; /* Window credits */
|
||||
u32 status; /* Window status used in OS */
|
||||
enum vas_cop_type cop;
|
||||
struct vas_user_win_ref task_ref;
|
||||
char *dbgname;
|
||||
|
|
|
@ -2,74 +2,9 @@
|
|||
#ifndef _ASM_POWERPC_VDSO_GETTIMEOFDAY_H
|
||||
#define _ASM_POWERPC_VDSO_GETTIMEOFDAY_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <asm/page.h>
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
#include <asm/ppc_asm.h>
|
||||
|
||||
/*
|
||||
* The macros sets two stack frames, one for the caller and one for the callee
|
||||
* because there are no requirement for the caller to set a stack frame when
|
||||
* calling VDSO so it may have omitted to set one, especially on PPC64
|
||||
*/
|
||||
|
||||
.macro cvdso_call funct
|
||||
.cfi_startproc
|
||||
PPC_STLU r1, -PPC_MIN_STKFRM(r1)
|
||||
mflr r0
|
||||
.cfi_register lr, r0
|
||||
PPC_STLU r1, -PPC_MIN_STKFRM(r1)
|
||||
PPC_STL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
||||
#ifdef __powerpc64__
|
||||
PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1)
|
||||
#endif
|
||||
get_datapage r5
|
||||
addi r5, r5, VDSO_DATA_OFFSET
|
||||
bl DOTSYM(\funct)
|
||||
PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
||||
#ifdef __powerpc64__
|
||||
PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1)
|
||||
#endif
|
||||
cmpwi r3, 0
|
||||
mtlr r0
|
||||
.cfi_restore lr
|
||||
addi r1, r1, 2 * PPC_MIN_STKFRM
|
||||
crclr so
|
||||
beqlr+
|
||||
crset so
|
||||
neg r3, r3
|
||||
blr
|
||||
.cfi_endproc
|
||||
.endm
|
||||
|
||||
.macro cvdso_call_time funct
|
||||
.cfi_startproc
|
||||
PPC_STLU r1, -PPC_MIN_STKFRM(r1)
|
||||
mflr r0
|
||||
.cfi_register lr, r0
|
||||
PPC_STLU r1, -PPC_MIN_STKFRM(r1)
|
||||
PPC_STL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
||||
#ifdef __powerpc64__
|
||||
PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1)
|
||||
#endif
|
||||
get_datapage r4
|
||||
addi r4, r4, VDSO_DATA_OFFSET
|
||||
bl DOTSYM(\funct)
|
||||
PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
||||
#ifdef __powerpc64__
|
||||
PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1)
|
||||
#endif
|
||||
crclr so
|
||||
mtlr r0
|
||||
.cfi_restore lr
|
||||
addi r1, r1, 2 * PPC_MIN_STKFRM
|
||||
blr
|
||||
.cfi_endproc
|
||||
.endm
|
||||
|
||||
#else
|
||||
|
||||
#include <asm/vdso/timebase.h>
|
||||
#include <asm/barrier.h>
|
||||
#include <asm/unistd.h>
|
||||
|
|
|
@ -289,12 +289,4 @@ typedef elf_fpreg_t elf_vsrreghalf_t32[ELF_NVSRHALFREG];
|
|||
/* Keep this the last entry. */
|
||||
#define R_PPC64_NUM 253
|
||||
|
||||
/* There's actually a third entry here, but it's unused */
|
||||
struct ppc64_opd_entry
|
||||
{
|
||||
unsigned long funcaddr;
|
||||
unsigned long r2;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _UAPI_ASM_POWERPC_ELF_H */
|
||||
|
|
|
@ -116,6 +116,22 @@ struct nd_papr_pdsm_health {
|
|||
};
|
||||
};
|
||||
|
||||
/* Flags for injecting specific smart errors */
|
||||
#define PDSM_SMART_INJECT_HEALTH_FATAL (1 << 0)
|
||||
#define PDSM_SMART_INJECT_BAD_SHUTDOWN (1 << 1)
|
||||
|
||||
struct nd_papr_pdsm_smart_inject {
|
||||
union {
|
||||
struct {
|
||||
/* One or more of PDSM_SMART_INJECT_ */
|
||||
__u32 flags;
|
||||
__u8 fatal_enable;
|
||||
__u8 unsafe_shutdown_enable;
|
||||
};
|
||||
__u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Methods to be embedded in ND_CMD_CALL request. These are sent to the kernel
|
||||
* via 'nd_cmd_pkg.nd_command' member of the ioctl struct
|
||||
|
@ -123,12 +139,14 @@ struct nd_papr_pdsm_health {
|
|||
enum papr_pdsm {
|
||||
PAPR_PDSM_MIN = 0x0,
|
||||
PAPR_PDSM_HEALTH,
|
||||
PAPR_PDSM_SMART_INJECT,
|
||||
PAPR_PDSM_MAX,
|
||||
};
|
||||
|
||||
/* Maximal union that can hold all possible payload types */
|
||||
union nd_pdsm_payload {
|
||||
struct nd_papr_pdsm_health health;
|
||||
struct nd_papr_pdsm_smart_inject smart_inject;
|
||||
__u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
|
||||
} __packed;
|
||||
|
||||
|
|
|
@ -194,8 +194,8 @@ targets += prom_init_check
|
|||
clean-files := vmlinux.lds
|
||||
|
||||
# Force dependency (incbin is bad)
|
||||
$(obj)/vdso32_wrapper.o : $(obj)/vdso32/vdso32.so.dbg
|
||||
$(obj)/vdso64_wrapper.o : $(obj)/vdso64/vdso64.so.dbg
|
||||
$(obj)/vdso32_wrapper.o : $(obj)/vdso/vdso32.so.dbg
|
||||
$(obj)/vdso64_wrapper.o : $(obj)/vdso/vdso64.so.dbg
|
||||
|
||||
# for cleaning
|
||||
subdir- += vdso32 vdso64
|
||||
subdir- += vdso
|
||||
|
|
|
@ -94,7 +94,7 @@ int main(void)
|
|||
OFFSET(TASK_CPU, task_struct, thread_info.cpu);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LIVEPATCH
|
||||
#ifdef CONFIG_LIVEPATCH_64
|
||||
OFFSET(TI_livepatch_sp, thread_info, livepatch_sp);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/asm-prototypes.h>
|
||||
|
||||
/*
|
||||
* We're called here very early in the boot.
|
||||
|
|
|
@ -1643,9 +1643,11 @@ int __init setup_fadump(void)
|
|||
if (fw_dump.ops->fadump_process(&fw_dump) < 0)
|
||||
fadump_invalidate_release_mem();
|
||||
}
|
||||
/* Initialize the kernel dump memory structure for FAD registration. */
|
||||
else if (fw_dump.reserve_dump_area_size)
|
||||
/* Initialize the kernel dump memory structure and register with f/w */
|
||||
else if (fw_dump.reserve_dump_area_size) {
|
||||
fw_dump.ops->fadump_init_mem_struct(&fw_dump);
|
||||
register_fadump();
|
||||
}
|
||||
|
||||
/*
|
||||
* In case of panic, fadump is triggered via ppc_panic_event()
|
||||
|
@ -1657,7 +1659,12 @@ int __init setup_fadump(void)
|
|||
|
||||
return 1;
|
||||
}
|
||||
subsys_initcall(setup_fadump);
|
||||
/*
|
||||
* Use subsys_initcall_sync() here because there is dependency with
|
||||
* crash_save_vmcoreinfo_init(), which mush run first to ensure vmcoreinfo initialization
|
||||
* is done before regisering with f/w.
|
||||
*/
|
||||
subsys_initcall_sync(setup_fadump);
|
||||
#else /* !CONFIG_PRESERVE_FA_DUMP */
|
||||
|
||||
/* Scan the Firmware Assisted dump configuration details. */
|
||||
|
|
|
@ -53,8 +53,8 @@
|
|||
* This is all going to change RSN when we add bi_recs....... -- Dan
|
||||
*/
|
||||
__HEAD
|
||||
_ENTRY(_stext);
|
||||
_ENTRY(_start);
|
||||
_GLOBAL(_stext);
|
||||
_GLOBAL(_start);
|
||||
|
||||
mr r31,r3 /* save device tree ptr */
|
||||
|
||||
|
@ -82,19 +82,19 @@ turn_on_mmu:
|
|||
*/
|
||||
. = 0xc0
|
||||
crit_save:
|
||||
_ENTRY(crit_r10)
|
||||
_GLOBAL(crit_r10)
|
||||
.space 4
|
||||
_ENTRY(crit_r11)
|
||||
_GLOBAL(crit_r11)
|
||||
.space 4
|
||||
_ENTRY(crit_srr0)
|
||||
_GLOBAL(crit_srr0)
|
||||
.space 4
|
||||
_ENTRY(crit_srr1)
|
||||
_GLOBAL(crit_srr1)
|
||||
.space 4
|
||||
_ENTRY(crit_r1)
|
||||
_GLOBAL(crit_r1)
|
||||
.space 4
|
||||
_ENTRY(crit_dear)
|
||||
_GLOBAL(crit_dear)
|
||||
.space 4
|
||||
_ENTRY(crit_esr)
|
||||
_GLOBAL(crit_esr)
|
||||
.space 4
|
||||
|
||||
/*
|
||||
|
|
|
@ -52,8 +52,8 @@
|
|||
*
|
||||
*/
|
||||
__HEAD
|
||||
_ENTRY(_stext);
|
||||
_ENTRY(_start);
|
||||
_GLOBAL(_stext);
|
||||
_GLOBAL(_start);
|
||||
/*
|
||||
* Reserve a word at a fixed location to store the address
|
||||
* of abatron_pteptrs
|
||||
|
|
|
@ -53,8 +53,8 @@
|
|||
#define PAGE_SHIFT_8M 23
|
||||
|
||||
__HEAD
|
||||
_ENTRY(_stext);
|
||||
_ENTRY(_start);
|
||||
_GLOBAL(_stext);
|
||||
_GLOBAL(_start);
|
||||
|
||||
/* MPC8xx
|
||||
* This port was done on an MBX board with an 860. Right now I only
|
||||
|
|
|
@ -50,16 +50,13 @@
|
|||
mtspr SPRN_DBAT##n##L,RB
|
||||
|
||||
__HEAD
|
||||
.stabs "arch/powerpc/kernel/",N_SO,0,0,0f
|
||||
.stabs "head_book3s_32.S",N_SO,0,0,0f
|
||||
0:
|
||||
_ENTRY(_stext);
|
||||
_GLOBAL(_stext);
|
||||
|
||||
/*
|
||||
* _start is defined this way because the XCOFF loader in the OpenFirmware
|
||||
* on the powermac expects the entry point to be a procedure descriptor.
|
||||
*/
|
||||
_ENTRY(_start);
|
||||
_GLOBAL(_start);
|
||||
/*
|
||||
* These are here for legacy reasons, the kernel used to
|
||||
* need to look like a coff function entry for the pmac
|
||||
|
@ -504,14 +501,12 @@ DataLoadTLBMiss:
|
|||
lwz r0,0(r2) /* get linux-style pte */
|
||||
andc. r1,r1,r0 /* check access & ~permission */
|
||||
bne- DataAddressInvalid /* return if access not permitted */
|
||||
/*
|
||||
* NOTE! We are assuming this is not an SMP system, otherwise
|
||||
* we would need to update the pte atomically with lwarx/stwcx.
|
||||
*/
|
||||
/* Convert linux-style PTE to low word of PPC-style PTE */
|
||||
rlwinm r1,r0,32-9,30,30 /* _PAGE_RW -> PP msb */
|
||||
rlwimi r0,r0,32-1,30,30 /* _PAGE_USER -> PP msb */
|
||||
rlwimi r1,r0,32-3,24,24 /* _PAGE_RW -> _PAGE_DIRTY */
|
||||
rlwimi r0,r0,32-1,31,31 /* _PAGE_USER -> PP lsb */
|
||||
xori r1,r1,_PAGE_DIRTY /* clear dirty when not rw */
|
||||
ori r1,r1,0xe04 /* clear out reserved bits */
|
||||
andc r1,r0,r1 /* PP = user? rw? 1: 3: 0 */
|
||||
BEGIN_FTR_SECTION
|
||||
|
@ -586,10 +581,6 @@ DataStoreTLBMiss:
|
|||
lwz r0,0(r2) /* get linux-style pte */
|
||||
andc. r1,r1,r0 /* check access & ~permission */
|
||||
bne- DataAddressInvalid /* return if access not permitted */
|
||||
/*
|
||||
* NOTE! We are assuming this is not an SMP system, otherwise
|
||||
* we would need to update the pte atomically with lwarx/stwcx.
|
||||
*/
|
||||
/* Convert linux-style PTE to low word of PPC-style PTE */
|
||||
rlwimi r0,r0,32-2,31,31 /* _PAGE_USER -> PP lsb */
|
||||
li r1,0xe06 /* clear out reserved bits & PP msb */
|
||||
|
@ -784,7 +775,7 @@ relocate_kernel:
|
|||
* r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset
|
||||
* on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5.
|
||||
*/
|
||||
_ENTRY(copy_and_flush)
|
||||
_GLOBAL(copy_and_flush)
|
||||
addi r5,r5,-4
|
||||
addi r6,r6,-4
|
||||
4: li r0,L1_CACHE_BYTES/4
|
||||
|
@ -1082,7 +1073,7 @@ BEGIN_MMU_FTR_SECTION
|
|||
END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
|
||||
blr
|
||||
|
||||
_ENTRY(update_bats)
|
||||
_GLOBAL(update_bats)
|
||||
lis r4, 1f@h
|
||||
ori r4, r4, 1f@l
|
||||
tophys(r4, r4)
|
||||
|
|
|
@ -54,8 +54,8 @@
|
|||
*
|
||||
*/
|
||||
__HEAD
|
||||
_ENTRY(_stext);
|
||||
_ENTRY(_start);
|
||||
_GLOBAL(_stext);
|
||||
_GLOBAL(_start);
|
||||
/*
|
||||
* Reserve a word at a fixed location to store the address
|
||||
* of abatron_pteptrs
|
||||
|
@ -154,7 +154,7 @@ _ENTRY(_start);
|
|||
* if needed
|
||||
*/
|
||||
|
||||
_ENTRY(__early_start)
|
||||
_GLOBAL(__early_start)
|
||||
LOAD_REG_ADDR_PIC(r20, kernstart_virt_addr)
|
||||
lwz r20,0(r20)
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include <linux/compat.h>
|
||||
#include <linux/sched/debug.h> /* for show_regs */
|
||||
|
||||
#include <asm/asm-prototypes.h>
|
||||
#include <asm/kup.h>
|
||||
#include <asm/cputime.h>
|
||||
#include <asm/hw_irq.h>
|
||||
|
|
|
@ -64,7 +64,6 @@
|
|||
#include <asm/udbg.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/livepatch.h>
|
||||
#include <asm/asm-prototypes.h>
|
||||
#include <asm/hw_irq.h>
|
||||
#include <asm/softirq_stack.h>
|
||||
|
||||
|
|
|
@ -24,23 +24,12 @@
|
|||
#include <asm/machdep.h>
|
||||
#include <asm/mce.h>
|
||||
#include <asm/nmi.h>
|
||||
#include <asm/asm-prototypes.h>
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
static void machine_check_process_queued_event(struct irq_work *work);
|
||||
static void machine_check_ue_irq_work(struct irq_work *work);
|
||||
static void machine_check_ue_event(struct machine_check_event *evt);
|
||||
static void machine_process_ue_event(struct work_struct *work);
|
||||
|
||||
static struct irq_work mce_event_process_work = {
|
||||
.func = machine_check_process_queued_event,
|
||||
};
|
||||
|
||||
static struct irq_work mce_ue_event_irq_work = {
|
||||
.func = machine_check_ue_irq_work,
|
||||
};
|
||||
|
||||
static DECLARE_WORK(mce_ue_event_work, machine_process_ue_event);
|
||||
|
||||
static BLOCKING_NOTIFIER_HEAD(mce_notifier_list);
|
||||
|
@ -89,6 +78,13 @@ static void mce_set_error_info(struct machine_check_event *mce,
|
|||
}
|
||||
}
|
||||
|
||||
void mce_irq_work_queue(void)
|
||||
{
|
||||
/* Raise decrementer interrupt */
|
||||
arch_irq_work_raise();
|
||||
set_mce_pending_irq_work();
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode and save high level MCE information into per cpu buffer which
|
||||
* is an array of machine_check_event structure.
|
||||
|
@ -217,7 +213,7 @@ void release_mce_event(void)
|
|||
get_mce_event(NULL, true);
|
||||
}
|
||||
|
||||
static void machine_check_ue_irq_work(struct irq_work *work)
|
||||
static void machine_check_ue_work(void)
|
||||
{
|
||||
schedule_work(&mce_ue_event_work);
|
||||
}
|
||||
|
@ -239,7 +235,7 @@ static void machine_check_ue_event(struct machine_check_event *evt)
|
|||
evt, sizeof(*evt));
|
||||
|
||||
/* Queue work to process this event later. */
|
||||
irq_work_queue(&mce_ue_event_irq_work);
|
||||
mce_irq_work_queue();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -249,7 +245,6 @@ void machine_check_queue_event(void)
|
|||
{
|
||||
int index;
|
||||
struct machine_check_event evt;
|
||||
unsigned long msr;
|
||||
|
||||
if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
|
||||
return;
|
||||
|
@ -263,20 +258,7 @@ void machine_check_queue_event(void)
|
|||
memcpy(&local_paca->mce_info->mce_event_queue[index],
|
||||
&evt, sizeof(evt));
|
||||
|
||||
/*
|
||||
* Queue irq work to process this event later. Before
|
||||
* queuing the work enable translation for non radix LPAR,
|
||||
* as irq_work_queue may try to access memory outside RMO
|
||||
* region.
|
||||
*/
|
||||
if (!radix_enabled() && firmware_has_feature(FW_FEATURE_LPAR)) {
|
||||
msr = mfmsr();
|
||||
mtmsr(msr | MSR_IR | MSR_DR);
|
||||
irq_work_queue(&mce_event_process_work);
|
||||
mtmsr(msr);
|
||||
} else {
|
||||
irq_work_queue(&mce_event_process_work);
|
||||
}
|
||||
mce_irq_work_queue();
|
||||
}
|
||||
|
||||
void mce_common_process_ue(struct pt_regs *regs,
|
||||
|
@ -338,7 +320,7 @@ static void machine_process_ue_event(struct work_struct *work)
|
|||
* process pending MCE event from the mce event queue. This function will be
|
||||
* called during syscall exit.
|
||||
*/
|
||||
static void machine_check_process_queued_event(struct irq_work *work)
|
||||
static void machine_check_process_queued_event(void)
|
||||
{
|
||||
int index;
|
||||
struct machine_check_event *evt;
|
||||
|
@ -363,6 +345,27 @@ static void machine_check_process_queued_event(struct irq_work *work)
|
|||
}
|
||||
}
|
||||
|
||||
void set_mce_pending_irq_work(void)
|
||||
{
|
||||
local_paca->mce_pending_irq_work = 1;
|
||||
}
|
||||
|
||||
void clear_mce_pending_irq_work(void)
|
||||
{
|
||||
local_paca->mce_pending_irq_work = 0;
|
||||
}
|
||||
|
||||
void mce_run_irq_context_handlers(void)
|
||||
{
|
||||
if (unlikely(local_paca->mce_pending_irq_work)) {
|
||||
if (ppc_md.machine_check_log_err)
|
||||
ppc_md.machine_check_log_err();
|
||||
machine_check_process_queued_event();
|
||||
machine_check_ue_work();
|
||||
clear_mce_pending_irq_work();
|
||||
}
|
||||
}
|
||||
|
||||
void machine_check_print_event_info(struct machine_check_event *evt,
|
||||
bool user_mode, bool in_guest)
|
||||
{
|
||||
|
@ -401,14 +404,14 @@ void machine_check_print_event_info(struct machine_check_event *evt,
|
|||
static const char *mc_ra_types[] = {
|
||||
"Indeterminate",
|
||||
"Instruction fetch (bad)",
|
||||
"Instruction fetch (foreign)",
|
||||
"Instruction fetch (foreign/control memory)",
|
||||
"Page table walk ifetch (bad)",
|
||||
"Page table walk ifetch (foreign)",
|
||||
"Page table walk ifetch (foreign/control memory)",
|
||||
"Load (bad)",
|
||||
"Store (bad)",
|
||||
"Page table walk Load/Store (bad)",
|
||||
"Page table walk Load/Store (foreign)",
|
||||
"Load/Store (foreign)",
|
||||
"Page table walk Load/Store (foreign/control memory)",
|
||||
"Load/Store (foreign/control memory)",
|
||||
};
|
||||
static const char *mc_link_types[] = {
|
||||
"Indeterminate",
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/bug.h>
|
||||
#include <linux/sort.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/code-patching.h>
|
||||
|
||||
/* Count how many different relocations (different symbol, different
|
||||
addend) */
|
||||
|
@ -174,15 +175,25 @@ static uint32_t do_plt_call(void *location,
|
|||
entry++;
|
||||
}
|
||||
|
||||
entry->jump[0] = PPC_RAW_LIS(_R12, PPC_HA(val));
|
||||
entry->jump[1] = PPC_RAW_ADDI(_R12, _R12, PPC_LO(val));
|
||||
entry->jump[2] = PPC_RAW_MTCTR(_R12);
|
||||
entry->jump[3] = PPC_RAW_BCTR();
|
||||
if (patch_instruction(&entry->jump[0], ppc_inst(PPC_RAW_LIS(_R12, PPC_HA(val)))))
|
||||
return 0;
|
||||
if (patch_instruction(&entry->jump[1], ppc_inst(PPC_RAW_ADDI(_R12, _R12, PPC_LO(val)))))
|
||||
return 0;
|
||||
if (patch_instruction(&entry->jump[2], ppc_inst(PPC_RAW_MTCTR(_R12))))
|
||||
return 0;
|
||||
if (patch_instruction(&entry->jump[3], ppc_inst(PPC_RAW_BCTR())))
|
||||
return 0;
|
||||
|
||||
pr_debug("Initialized plt for 0x%x at %p\n", val, entry);
|
||||
return (uint32_t)entry;
|
||||
}
|
||||
|
||||
static int patch_location_16(uint32_t *loc, u16 value)
|
||||
{
|
||||
loc = PTR_ALIGN_DOWN(loc, sizeof(u32));
|
||||
return patch_instruction(loc, ppc_inst((*loc & 0xffff0000) | value));
|
||||
}
|
||||
|
||||
int apply_relocate_add(Elf32_Shdr *sechdrs,
|
||||
const char *strtab,
|
||||
unsigned int symindex,
|
||||
|
@ -216,37 +227,42 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
|
|||
|
||||
case R_PPC_ADDR16_LO:
|
||||
/* Low half of the symbol */
|
||||
*(uint16_t *)location = value;
|
||||
if (patch_location_16(location, PPC_LO(value)))
|
||||
return -EFAULT;
|
||||
break;
|
||||
|
||||
case R_PPC_ADDR16_HI:
|
||||
/* Higher half of the symbol */
|
||||
*(uint16_t *)location = (value >> 16);
|
||||
if (patch_location_16(location, PPC_HI(value)))
|
||||
return -EFAULT;
|
||||
break;
|
||||
|
||||
case R_PPC_ADDR16_HA:
|
||||
/* Sign-adjusted lower 16 bits: PPC ELF ABI says:
|
||||
(((x >> 16) + ((x & 0x8000) ? 1 : 0))) & 0xFFFF.
|
||||
This is the same, only sane.
|
||||
*/
|
||||
*(uint16_t *)location = (value + 0x8000) >> 16;
|
||||
if (patch_location_16(location, PPC_HA(value)))
|
||||
return -EFAULT;
|
||||
break;
|
||||
|
||||
case R_PPC_REL24:
|
||||
if ((int)(value - (uint32_t)location) < -0x02000000
|
||||
|| (int)(value - (uint32_t)location) >= 0x02000000)
|
||||
|| (int)(value - (uint32_t)location) >= 0x02000000) {
|
||||
value = do_plt_call(location, value,
|
||||
sechdrs, module);
|
||||
if (!value)
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Only replace bits 2 through 26 */
|
||||
pr_debug("REL24 value = %08X. location = %08X\n",
|
||||
value, (uint32_t)location);
|
||||
pr_debug("Location before: %08X.\n",
|
||||
*(uint32_t *)location);
|
||||
*(uint32_t *)location
|
||||
= (*(uint32_t *)location & ~0x03fffffc)
|
||||
value = (*(uint32_t *)location & ~0x03fffffc)
|
||||
| ((value - (uint32_t)location)
|
||||
& 0x03fffffc);
|
||||
|
||||
if (patch_instruction(location, ppc_inst(value)))
|
||||
return -EFAULT;
|
||||
|
||||
pr_debug("Location after: %08X.\n",
|
||||
*(uint32_t *)location);
|
||||
pr_debug("ie. jump to %08X+%08X = %08X\n",
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/ftrace.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/module.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/code-patching.h>
|
||||
|
@ -32,20 +33,13 @@
|
|||
|
||||
#ifdef PPC64_ELF_ABI_v2
|
||||
|
||||
/* An address is simply the address of the function. */
|
||||
typedef unsigned long func_desc_t;
|
||||
|
||||
static func_desc_t func_desc(unsigned long addr)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
static unsigned long func_addr(unsigned long addr)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
static unsigned long stub_func_addr(func_desc_t func)
|
||||
{
|
||||
return func;
|
||||
func_desc_t desc = {
|
||||
.addr = addr,
|
||||
};
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
/* PowerPC64 specific values for the Elf64_Sym st_other field. */
|
||||
|
@ -63,20 +57,9 @@ static unsigned int local_entry_offset(const Elf64_Sym *sym)
|
|||
}
|
||||
#else
|
||||
|
||||
/* An address is address of the OPD entry, which contains address of fn. */
|
||||
typedef struct ppc64_opd_entry func_desc_t;
|
||||
|
||||
static func_desc_t func_desc(unsigned long addr)
|
||||
{
|
||||
return *(struct ppc64_opd_entry *)addr;
|
||||
}
|
||||
static unsigned long func_addr(unsigned long addr)
|
||||
{
|
||||
return func_desc(addr).funcaddr;
|
||||
}
|
||||
static unsigned long stub_func_addr(func_desc_t func)
|
||||
{
|
||||
return func.funcaddr;
|
||||
return *(struct func_desc *)addr;
|
||||
}
|
||||
static unsigned int local_entry_offset(const Elf64_Sym *sym)
|
||||
{
|
||||
|
@ -93,6 +76,16 @@ void *dereference_module_function_descriptor(struct module *mod, void *ptr)
|
|||
}
|
||||
#endif
|
||||
|
||||
static unsigned long func_addr(unsigned long addr)
|
||||
{
|
||||
return func_desc(addr).addr;
|
||||
}
|
||||
|
||||
static unsigned long stub_func_addr(func_desc_t func)
|
||||
{
|
||||
return func.addr;
|
||||
}
|
||||
|
||||
#define STUB_MAGIC 0x73747562 /* stub */
|
||||
|
||||
/* Like PPC32, we need little trampolines to do > 24-bit jumps (into
|
||||
|
@ -187,7 +180,7 @@ static int relacmp(const void *_x, const void *_y)
|
|||
static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
|
||||
const Elf64_Shdr *sechdrs)
|
||||
{
|
||||
/* One extra reloc so it's always 0-funcaddr terminated */
|
||||
/* One extra reloc so it's always 0-addr terminated */
|
||||
unsigned long relocs = 1;
|
||||
unsigned i;
|
||||
|
||||
|
@ -277,6 +270,12 @@ static Elf64_Sym *find_dot_toc(Elf64_Shdr *sechdrs,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool module_init_section(const char *name)
|
||||
{
|
||||
/* We don't handle .init for the moment: always return false. */
|
||||
return false;
|
||||
}
|
||||
|
||||
int module_frob_arch_sections(Elf64_Ehdr *hdr,
|
||||
Elf64_Shdr *sechdrs,
|
||||
char *secstrings,
|
||||
|
@ -286,7 +285,6 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
|
|||
|
||||
/* Find .toc and .stubs sections, symtab and strtab */
|
||||
for (i = 1; i < hdr->e_shnum; i++) {
|
||||
char *p;
|
||||
if (strcmp(secstrings + sechdrs[i].sh_name, ".stubs") == 0)
|
||||
me->arch.stubs_section = i;
|
||||
else if (strcmp(secstrings + sechdrs[i].sh_name, ".toc") == 0) {
|
||||
|
@ -298,10 +296,6 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
|
|||
dedotify_versions((void *)hdr + sechdrs[i].sh_offset,
|
||||
sechdrs[i].sh_size);
|
||||
|
||||
/* We don't handle .init for the moment: rename to _init */
|
||||
while ((p = strstr(secstrings + sechdrs[i].sh_name, ".init")))
|
||||
p[0] = '_';
|
||||
|
||||
if (sechdrs[i].sh_type == SHT_SYMTAB)
|
||||
dedotify((void *)hdr + sechdrs[i].sh_offset,
|
||||
sechdrs[i].sh_size / sizeof(Elf64_Sym),
|
||||
|
@ -428,7 +422,7 @@ static inline int create_stub(const Elf64_Shdr *sechdrs,
|
|||
if (is_mprofile_ftrace_call(name))
|
||||
return create_ftrace_stub(entry, addr, me);
|
||||
|
||||
for (i = 0; i < sizeof(ppc64_stub_insns) / sizeof(u32); i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(ppc64_stub_insns); i++) {
|
||||
if (patch_instruction(&entry->jump[i],
|
||||
ppc_inst(ppc64_stub_insns[i])))
|
||||
return 0;
|
||||
|
|
|
@ -352,6 +352,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
|
|||
be32_to_cpu(intserv[found_thread]));
|
||||
boot_cpuid = found;
|
||||
|
||||
// Pass the boot CPU's hard CPU id back to our caller
|
||||
*((u32 *)data) = be32_to_cpu(intserv[found_thread]);
|
||||
|
||||
/*
|
||||
* PAPR defines "logical" PVR values for cpus that
|
||||
* meet various levels of the architecture:
|
||||
|
@ -388,9 +391,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
|
|||
cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
|
||||
else if (!dt_cpu_ftrs_in_use())
|
||||
cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
|
||||
allocate_paca(boot_cpuid);
|
||||
#endif
|
||||
set_hard_smp_processor_id(found, be32_to_cpu(intserv[found_thread]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -714,6 +715,7 @@ static inline void save_fscr_to_task(void) {}
|
|||
|
||||
void __init early_init_devtree(void *params)
|
||||
{
|
||||
u32 boot_cpu_hwid;
|
||||
phys_addr_t limit;
|
||||
|
||||
DBG(" -> early_init_devtree(%px)\n", params);
|
||||
|
@ -790,8 +792,6 @@ void __init early_init_devtree(void *params)
|
|||
* FIXME .. and the initrd too? */
|
||||
move_device_tree();
|
||||
|
||||
allocate_paca_ptrs();
|
||||
|
||||
DBG("Scanning CPUs ...\n");
|
||||
|
||||
dt_cpu_ftrs_scan();
|
||||
|
@ -799,7 +799,7 @@ void __init early_init_devtree(void *params)
|
|||
/* Retrieve CPU related informations from the flat tree
|
||||
* (altivec support, boot CPU ID, ...)
|
||||
*/
|
||||
of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
|
||||
of_scan_flat_dt(early_init_dt_scan_cpus, &boot_cpu_hwid);
|
||||
if (boot_cpuid < 0) {
|
||||
printk("Failed to identify boot CPU !\n");
|
||||
BUG();
|
||||
|
@ -816,6 +816,11 @@ void __init early_init_devtree(void *params)
|
|||
|
||||
mmu_early_init_devtree();
|
||||
|
||||
// NB. paca is not installed until later in early_setup()
|
||||
allocate_paca_ptrs();
|
||||
allocate_paca(boot_cpuid);
|
||||
set_hard_smp_processor_id(boot_cpuid, boot_cpu_hwid);
|
||||
|
||||
#ifdef CONFIG_PPC_POWERNV
|
||||
/* Scan and build the list of machine check recoverable ranges */
|
||||
of_scan_flat_dt(early_init_dt_scan_recoverable_ranges, NULL);
|
||||
|
|
|
@ -841,7 +841,7 @@ static const struct user_regset_view user_ppc_compat_view = {
|
|||
|
||||
const struct user_regset_view *task_user_regset_view(struct task_struct *task)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_PPC64) && test_tsk_thread_flag(task, TIF_32BIT))
|
||||
if (IS_ENABLED(CONFIG_COMPAT) && is_tsk_32bit_task(task))
|
||||
return &user_ppc_compat_view;
|
||||
return &user_ppc_native_view;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <linux/syscalls.h>
|
||||
|
||||
#include <asm/switch_to.h>
|
||||
#include <asm/asm-prototypes.h>
|
||||
#include <asm/debug.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
|
@ -445,4 +444,10 @@ void __init pt_regs_check(void)
|
|||
* real registers.
|
||||
*/
|
||||
BUILD_BUG_ON(PT_DSCR < sizeof(struct user_pt_regs) / sizeof(unsigned long));
|
||||
|
||||
#ifdef PPC64_ELF_ABI_v1
|
||||
BUILD_BUG_ON(!IS_ENABLED(CONFIG_HAVE_FUNCTION_DESCRIPTORS));
|
||||
#else
|
||||
BUILD_BUG_ON(IS_ENABLED(CONFIG_HAVE_FUNCTION_DESCRIPTORS));
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
#include <asm/ppc_asm.h>
|
||||
|
||||
RELA = 7
|
||||
RELACOUNT = 0x6ffffff9
|
||||
RELASZ = 8
|
||||
RELAENT = 9
|
||||
R_PPC64_RELATIVE = 22
|
||||
R_PPC64_UADDR64 = 43
|
||||
|
||||
/*
|
||||
* r3 = desired final address of kernel
|
||||
|
@ -25,29 +27,38 @@ _GLOBAL(relocate)
|
|||
add r9,r9,r12 /* r9 has runtime addr of .rela.dyn section */
|
||||
ld r10,(p_st - 0b)(r12)
|
||||
add r10,r10,r12 /* r10 has runtime addr of _stext */
|
||||
ld r13,(p_sym - 0b)(r12)
|
||||
add r13,r13,r12 /* r13 has runtime addr of .dynsym */
|
||||
|
||||
/*
|
||||
* Scan the dynamic section for the RELA and RELACOUNT entries.
|
||||
* Scan the dynamic section for the RELA, RELASZ and RELAENT entries.
|
||||
*/
|
||||
li r7,0
|
||||
li r8,0
|
||||
1: ld r6,0(r11) /* get tag */
|
||||
.Ltags:
|
||||
ld r6,0(r11) /* get tag */
|
||||
cmpdi r6,0
|
||||
beq 4f /* end of list */
|
||||
beq .Lend_of_list /* end of list */
|
||||
cmpdi r6,RELA
|
||||
bne 2f
|
||||
ld r7,8(r11) /* get RELA pointer in r7 */
|
||||
b 3f
|
||||
2: addis r6,r6,(-RELACOUNT)@ha
|
||||
cmpdi r6,RELACOUNT@l
|
||||
b 4f
|
||||
2: cmpdi r6,RELASZ
|
||||
bne 3f
|
||||
ld r8,8(r11) /* get RELACOUNT value in r8 */
|
||||
3: addi r11,r11,16
|
||||
b 1b
|
||||
4: cmpdi r7,0 /* check we have both RELA and RELACOUNT */
|
||||
ld r8,8(r11) /* get RELASZ value in r8 */
|
||||
b 4f
|
||||
3: cmpdi r6,RELAENT
|
||||
bne 4f
|
||||
ld r12,8(r11) /* get RELAENT value in r12 */
|
||||
4: addi r11,r11,16
|
||||
b .Ltags
|
||||
.Lend_of_list:
|
||||
cmpdi r7,0 /* check we have RELA, RELASZ, RELAENT */
|
||||
cmpdi cr1,r8,0
|
||||
beq 6f
|
||||
beq cr1,6f
|
||||
beq .Lout
|
||||
beq cr1,.Lout
|
||||
cmpdi r12,0
|
||||
beq .Lout
|
||||
|
||||
/*
|
||||
* Work out linktime address of _stext and hence the
|
||||
|
@ -62,23 +73,39 @@ _GLOBAL(relocate)
|
|||
|
||||
/*
|
||||
* Run through the list of relocations and process the
|
||||
* R_PPC64_RELATIVE ones.
|
||||
* R_PPC64_RELATIVE and R_PPC64_UADDR64 ones.
|
||||
*/
|
||||
divd r8,r8,r12 /* RELASZ / RELAENT */
|
||||
mtctr r8
|
||||
5: ld r0,8(9) /* ELF64_R_TYPE(reloc->r_info) */
|
||||
.Lrels: ld r0,8(r9) /* ELF64_R_TYPE(reloc->r_info) */
|
||||
cmpdi r0,R_PPC64_RELATIVE
|
||||
bne 6f
|
||||
bne .Luaddr64
|
||||
ld r6,0(r9) /* reloc->r_offset */
|
||||
ld r0,16(r9) /* reloc->r_addend */
|
||||
b .Lstore
|
||||
.Luaddr64:
|
||||
srdi r14,r0,32 /* ELF64_R_SYM(reloc->r_info) */
|
||||
clrldi r0,r0,32
|
||||
cmpdi r0,R_PPC64_UADDR64
|
||||
bne .Lnext
|
||||
ld r6,0(r9)
|
||||
ld r0,16(r9)
|
||||
mulli r14,r14,24 /* 24 == sizeof(elf64_sym) */
|
||||
add r14,r14,r13 /* elf64_sym[ELF64_R_SYM] */
|
||||
ld r14,8(r14)
|
||||
add r0,r0,r14
|
||||
.Lstore:
|
||||
add r0,r0,r3
|
||||
stdx r0,r7,r6
|
||||
addi r9,r9,24
|
||||
bdnz 5b
|
||||
|
||||
6: blr
|
||||
.Lnext:
|
||||
add r9,r9,r12
|
||||
bdnz .Lrels
|
||||
.Lout:
|
||||
blr
|
||||
|
||||
.balign 8
|
||||
p_dyn: .8byte __dynamic_start - 0b
|
||||
p_rela: .8byte __rela_dyn_start - 0b
|
||||
p_sym: .8byte __dynamic_symtab - 0b
|
||||
p_st: .8byte _stext - 0b
|
||||
|
||||
|
|
|
@ -1313,6 +1313,12 @@ int __init early_init_dt_scan_rtas(unsigned long node,
|
|||
entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
|
||||
sizep = of_get_flat_dt_prop(node, "rtas-size", NULL);
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
/* need this feature to decide the crashkernel offset */
|
||||
if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL))
|
||||
powerpc_firmware_features |= FW_FEATURE_LPAR;
|
||||
#endif
|
||||
|
||||
if (basep && entryp && sizep) {
|
||||
rtas.base = *basep;
|
||||
rtas.entry = *entryp;
|
||||
|
|
|
@ -747,14 +747,29 @@ static int count_cache_flush_get(void *data, u64 *val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int link_stack_flush_get(void *data, u64 *val)
|
||||
{
|
||||
if (link_stack_flush_type == BRANCH_CACHE_FLUSH_NONE)
|
||||
*val = 0;
|
||||
else
|
||||
*val = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_count_cache_flush, count_cache_flush_get,
|
||||
count_cache_flush_set, "%llu\n");
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_link_stack_flush, link_stack_flush_get,
|
||||
count_cache_flush_set, "%llu\n");
|
||||
|
||||
static __init int count_cache_flush_debugfs_init(void)
|
||||
{
|
||||
debugfs_create_file_unsafe("count_cache_flush", 0600,
|
||||
arch_debugfs_dir, NULL,
|
||||
&fops_count_cache_flush);
|
||||
debugfs_create_file_unsafe("link_stack_flush", 0600,
|
||||
arch_debugfs_dir, NULL,
|
||||
&fops_link_stack_flush);
|
||||
return 0;
|
||||
}
|
||||
device_initcall(count_cache_flush_debugfs_init);
|
||||
|
|
|
@ -26,15 +26,18 @@ static ssize_t format_show(struct kobject *kobj, struct kobj_attribute *attr,
|
|||
const char *format;
|
||||
|
||||
node = of_find_compatible_node(NULL, NULL, "ibm,secvar-backend");
|
||||
if (!of_device_is_available(node))
|
||||
return -ENODEV;
|
||||
if (!of_device_is_available(node)) {
|
||||
rc = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = of_property_read_string(node, "format", &format);
|
||||
if (rc)
|
||||
return rc;
|
||||
goto out;
|
||||
|
||||
rc = sprintf(buf, "%s\n", format);
|
||||
|
||||
out:
|
||||
of_node_put(node);
|
||||
|
||||
return rc;
|
||||
|
|
|
@ -456,8 +456,8 @@ void __init smp_setup_cpu_maps(void)
|
|||
intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s",
|
||||
&len);
|
||||
if (intserv) {
|
||||
DBG(" ibm,ppc-interrupt-server#s -> %d threads\n",
|
||||
nthreads);
|
||||
DBG(" ibm,ppc-interrupt-server#s -> %lu threads\n",
|
||||
(len / sizeof(int)));
|
||||
} else {
|
||||
DBG(" no ibm,ppc-interrupt-server#s -> 1 thread\n");
|
||||
intserv = of_get_property(dn, "reg", &len);
|
||||
|
|
|
@ -67,7 +67,6 @@
|
|||
#include <asm/kup.h>
|
||||
#include <asm/early_ioremap.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/asm-prototypes.h>
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
|
|
|
@ -936,11 +936,11 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
|
|||
* descriptor is the entry address of signal and the second
|
||||
* entry is the TOC value we need to use.
|
||||
*/
|
||||
func_descr_t __user *funct_desc_ptr =
|
||||
(func_descr_t __user *) ksig->ka.sa.sa_handler;
|
||||
struct func_desc __user *ptr =
|
||||
(struct func_desc __user *)ksig->ka.sa.sa_handler;
|
||||
|
||||
err |= get_user(regs->ctr, &funct_desc_ptr->entry);
|
||||
err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
|
||||
err |= get_user(regs->ctr, &ptr->addr);
|
||||
err |= get_user(regs->gpr[2], &ptr->toc);
|
||||
}
|
||||
|
||||
/* enter the signal handler in native-endian mode */
|
||||
|
|
|
@ -57,7 +57,6 @@
|
|||
#include <asm/vdso.h>
|
||||
#include <asm/debug.h>
|
||||
#include <asm/kexec.h>
|
||||
#include <asm/asm-prototypes.h>
|
||||
#include <asm/cpu_has_feature.h>
|
||||
#include <asm/ftrace.h>
|
||||
#include <asm/kup.h>
|
||||
|
@ -716,7 +715,7 @@ void smp_send_stop(void)
|
|||
}
|
||||
#endif /* CONFIG_NMI_IPI */
|
||||
|
||||
struct task_struct *current_set[NR_CPUS];
|
||||
static struct task_struct *current_set[NR_CPUS];
|
||||
|
||||
static void smp_store_cpu_info(int id)
|
||||
{
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include <asm/syscalls.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/asm-prototypes.h>
|
||||
|
||||
static inline long do_mmap2(unsigned long addr, size_t len,
|
||||
unsigned long prot, unsigned long flags,
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <asm/cache.h>
|
||||
#include <asm/8xx_immap.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/asm-prototypes.h>
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
#include <asm/smp.h>
|
||||
#include <asm/vdso_datapage.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/asm-prototypes.h>
|
||||
#include <asm/mce.h>
|
||||
|
||||
/* powerpc clocksource/clockevent code */
|
||||
|
||||
|
@ -107,7 +107,12 @@ struct clock_event_device decrementer_clockevent = {
|
|||
};
|
||||
EXPORT_SYMBOL(decrementer_clockevent);
|
||||
|
||||
DEFINE_PER_CPU(u64, decrementers_next_tb);
|
||||
/*
|
||||
* This always puts next_tb beyond now, so the clock event will never fire
|
||||
* with the usual comparison, no need for a separate test for stopped.
|
||||
*/
|
||||
#define DEC_CLOCKEVENT_STOPPED ~0ULL
|
||||
DEFINE_PER_CPU(u64, decrementers_next_tb) = DEC_CLOCKEVENT_STOPPED;
|
||||
EXPORT_SYMBOL_GPL(decrementers_next_tb);
|
||||
static DEFINE_PER_CPU(struct clock_event_device, decrementers);
|
||||
|
||||
|
@ -582,8 +587,9 @@ void timer_rearm_host_dec(u64 now)
|
|||
local_paca->irq_happened |= PACA_IRQ_DEC;
|
||||
} else {
|
||||
now = *next_tb - now;
|
||||
if (now <= decrementer_max)
|
||||
set_dec_or_work(now);
|
||||
if (now > decrementer_max)
|
||||
now = decrementer_max;
|
||||
set_dec_or_work(now);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(timer_rearm_host_dec);
|
||||
|
@ -638,14 +644,13 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(timer_interrupt)
|
|||
|
||||
if (test_irq_work_pending()) {
|
||||
clear_irq_work_pending();
|
||||
mce_run_irq_context_handlers();
|
||||
irq_work_run();
|
||||
}
|
||||
|
||||
now = get_tb();
|
||||
if (now >= *next_tb) {
|
||||
*next_tb = ~(u64)0;
|
||||
if (evt->event_handler)
|
||||
evt->event_handler(evt);
|
||||
evt->event_handler(evt);
|
||||
__this_cpu_inc(irq_stat.timer_irqs_event);
|
||||
} else {
|
||||
now = *next_tb - now;
|
||||
|
@ -664,9 +669,6 @@ EXPORT_SYMBOL(timer_interrupt);
|
|||
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
|
||||
void timer_broadcast_interrupt(void)
|
||||
{
|
||||
u64 *next_tb = this_cpu_ptr(&decrementers_next_tb);
|
||||
|
||||
*next_tb = ~(u64)0;
|
||||
tick_receive_broadcast();
|
||||
__this_cpu_inc(irq_stat.broadcast_irqs_event);
|
||||
}
|
||||
|
@ -892,7 +894,9 @@ static int decrementer_set_next_event(unsigned long evt,
|
|||
|
||||
static int decrementer_shutdown(struct clock_event_device *dev)
|
||||
{
|
||||
decrementer_set_next_event(decrementer_max, dev);
|
||||
__this_cpu_write(decrementers_next_tb, DEC_CLOCKEVENT_STOPPED);
|
||||
set_dec_or_work(decrementer_max);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -443,7 +443,8 @@ restore_gprs:
|
|||
|
||||
REST_GPR(0, r7) /* GPR0 */
|
||||
REST_GPRS(2, 4, r7) /* GPR2-4 */
|
||||
REST_GPRS(8, 31, r7) /* GPR8-31 */
|
||||
REST_GPRS(8, 12, r7) /* GPR8-12 */
|
||||
REST_GPRS(14, 31, r7) /* GPR14-31 */
|
||||
|
||||
/* Load up PPR and DSCR here so we don't run with user values for long */
|
||||
mtspr SPRN_DSCR, r5
|
||||
|
@ -479,18 +480,24 @@ restore_gprs:
|
|||
REST_GPR(6, r7)
|
||||
|
||||
/*
|
||||
* Store r1 and r5 on the stack so that we can access them after we
|
||||
* clear MSR RI.
|
||||
* Store user r1 and r5 and r13 on the stack (in the unused save
|
||||
* areas / compiler reserved areas), so that we can access them after
|
||||
* we clear MSR RI.
|
||||
*/
|
||||
|
||||
REST_GPR(5, r7)
|
||||
std r5, -8(r1)
|
||||
ld r5, GPR1(r7)
|
||||
ld r5, GPR13(r7)
|
||||
std r5, -16(r1)
|
||||
ld r5, GPR1(r7)
|
||||
std r5, -24(r1)
|
||||
|
||||
REST_GPR(7, r7)
|
||||
|
||||
/* Clear MSR RI since we are about to use SCRATCH0. EE is already off */
|
||||
/* Stash the stack pointer away for use after recheckpoint */
|
||||
std r1, PACAR1(r13)
|
||||
|
||||
/* Clear MSR RI since we are about to clobber r13. EE is already off */
|
||||
li r5, 0
|
||||
mtmsrd r5, 1
|
||||
|
||||
|
@ -501,9 +508,9 @@ restore_gprs:
|
|||
* until we turn MSR RI back on.
|
||||
*/
|
||||
|
||||
SET_SCRATCH0(r1)
|
||||
ld r5, -8(r1)
|
||||
ld r1, -16(r1)
|
||||
ld r13, -16(r1)
|
||||
ld r1, -24(r1)
|
||||
|
||||
/* Commit register state as checkpointed state: */
|
||||
TRECHKPT
|
||||
|
@ -519,9 +526,9 @@ restore_gprs:
|
|||
*/
|
||||
|
||||
GET_PACA(r13)
|
||||
GET_SCRATCH0(r1)
|
||||
ld r1, PACAR1(r13)
|
||||
|
||||
/* R1 is restored, so we are recoverable again. EE is still off */
|
||||
/* R13, R1 is restored, so we are recoverable again. EE is still off */
|
||||
li r4, MSR_RI
|
||||
mtmsrd r4, 1
|
||||
|
||||
|
|
|
@ -8,13 +8,13 @@ ifdef CONFIG_FUNCTION_TRACER
|
|||
CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)
|
||||
endif
|
||||
|
||||
obj32-$(CONFIG_FUNCTION_TRACER) += ftrace_32.o
|
||||
obj64-$(CONFIG_FUNCTION_TRACER) += ftrace_64.o
|
||||
obj32-$(CONFIG_FUNCTION_TRACER) += ftrace_mprofile.o
|
||||
ifdef CONFIG_MPROFILE_KERNEL
|
||||
obj64-$(CONFIG_FUNCTION_TRACER) += ftrace_64_mprofile.o
|
||||
obj64-$(CONFIG_FUNCTION_TRACER) += ftrace_mprofile.o
|
||||
else
|
||||
obj64-$(CONFIG_FUNCTION_TRACER) += ftrace_64_pg.o
|
||||
endif
|
||||
obj-$(CONFIG_FUNCTION_TRACER) += ftrace_low.o
|
||||
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
|
||||
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
|
||||
obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include <asm/asm-prototypes.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/code-patching.h>
|
||||
#include <asm/ftrace.h>
|
||||
|
@ -910,30 +909,30 @@ int __init ftrace_dyn_arch_init(void)
|
|||
extern void ftrace_graph_call(void);
|
||||
extern void ftrace_graph_stub(void);
|
||||
|
||||
int ftrace_enable_ftrace_graph_caller(void)
|
||||
static int ftrace_modify_ftrace_graph_caller(bool enable)
|
||||
{
|
||||
unsigned long ip = (unsigned long)(&ftrace_graph_call);
|
||||
unsigned long addr = (unsigned long)(&ftrace_graph_caller);
|
||||
unsigned long stub = (unsigned long)(&ftrace_graph_stub);
|
||||
ppc_inst_t old, new;
|
||||
|
||||
old = ftrace_call_replace(ip, stub, 0);
|
||||
new = ftrace_call_replace(ip, addr, 0);
|
||||
if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_ARGS))
|
||||
return 0;
|
||||
|
||||
old = ftrace_call_replace(ip, enable ? stub : addr, 0);
|
||||
new = ftrace_call_replace(ip, enable ? addr : stub, 0);
|
||||
|
||||
return ftrace_modify_code(ip, old, new);
|
||||
}
|
||||
|
||||
int ftrace_enable_ftrace_graph_caller(void)
|
||||
{
|
||||
return ftrace_modify_ftrace_graph_caller(true);
|
||||
}
|
||||
|
||||
int ftrace_disable_ftrace_graph_caller(void)
|
||||
{
|
||||
unsigned long ip = (unsigned long)(&ftrace_graph_call);
|
||||
unsigned long addr = (unsigned long)(&ftrace_graph_caller);
|
||||
unsigned long stub = (unsigned long)(&ftrace_graph_stub);
|
||||
ppc_inst_t old, new;
|
||||
|
||||
old = ftrace_call_replace(ip, addr, 0);
|
||||
new = ftrace_call_replace(ip, stub, 0);
|
||||
|
||||
return ftrace_modify_code(ip, old, new);
|
||||
return ftrace_modify_ftrace_graph_caller(false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -944,6 +943,7 @@ unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip,
|
|||
unsigned long sp)
|
||||
{
|
||||
unsigned long return_hooker;
|
||||
int bit;
|
||||
|
||||
if (unlikely(ftrace_graph_is_dead()))
|
||||
goto out;
|
||||
|
@ -951,13 +951,27 @@ unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip,
|
|||
if (unlikely(atomic_read(¤t->tracing_graph_pause)))
|
||||
goto out;
|
||||
|
||||
bit = ftrace_test_recursion_trylock(ip, parent);
|
||||
if (bit < 0)
|
||||
goto out;
|
||||
|
||||
return_hooker = ppc_function_entry(return_to_handler);
|
||||
|
||||
if (!function_graph_enter(parent, ip, 0, (unsigned long *)sp))
|
||||
parent = return_hooker;
|
||||
|
||||
ftrace_test_recursion_unlock(bit);
|
||||
out:
|
||||
return parent;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
|
||||
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *op, struct ftrace_regs *fregs)
|
||||
{
|
||||
fregs->regs.link = prepare_ftrace_return(parent_ip, ip, fregs->regs.gpr[1]);
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
|
||||
#ifdef PPC64_ELF_ABI_v1
|
||||
|
|
|
@ -1,187 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Split from entry_32.S
|
||||
*/
|
||||
|
||||
#include <linux/magic.h>
|
||||
#include <asm/reg.h>
|
||||
#include <asm/ppc_asm.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/ftrace.h>
|
||||
#include <asm/export.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
_GLOBAL(mcount)
|
||||
_GLOBAL(_mcount)
|
||||
/*
|
||||
* It is required that _mcount on PPC32 must preserve the
|
||||
* link register. But we have r12 to play with. We use r12
|
||||
* to push the return address back to the caller of mcount
|
||||
* into the ctr register, restore the link register and
|
||||
* then jump back using the ctr register.
|
||||
*/
|
||||
mflr r12
|
||||
mtctr r12
|
||||
mtlr r0
|
||||
bctr
|
||||
EXPORT_SYMBOL(_mcount)
|
||||
|
||||
_GLOBAL(ftrace_caller)
|
||||
MCOUNT_SAVE_FRAME
|
||||
/* r3 ends up with link register */
|
||||
subi r3, r3, MCOUNT_INSN_SIZE
|
||||
lis r5,function_trace_op@ha
|
||||
lwz r5,function_trace_op@l(r5)
|
||||
li r6, 0
|
||||
.globl ftrace_call
|
||||
ftrace_call:
|
||||
bl ftrace_stub
|
||||
nop
|
||||
MCOUNT_RESTORE_FRAME
|
||||
ftrace_caller_common:
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
.globl ftrace_graph_call
|
||||
ftrace_graph_call:
|
||||
b ftrace_graph_stub
|
||||
_GLOBAL(ftrace_graph_stub)
|
||||
#endif
|
||||
/* old link register ends up in ctr reg */
|
||||
bctr
|
||||
|
||||
|
||||
_GLOBAL(ftrace_stub)
|
||||
blr
|
||||
|
||||
_GLOBAL(ftrace_regs_caller)
|
||||
/* Save the original return address in A's stack frame */
|
||||
stw r0,LRSAVE(r1)
|
||||
|
||||
/* Create our stack frame + pt_regs */
|
||||
stwu r1,-INT_FRAME_SIZE(r1)
|
||||
|
||||
/* Save all gprs to pt_regs */
|
||||
stw r0, GPR0(r1)
|
||||
stmw r2, GPR2(r1)
|
||||
|
||||
/* Save previous stack pointer (r1) */
|
||||
addi r8, r1, INT_FRAME_SIZE
|
||||
stw r8, GPR1(r1)
|
||||
|
||||
/* Load special regs for save below */
|
||||
mfmsr r8
|
||||
mfctr r9
|
||||
mfxer r10
|
||||
mfcr r11
|
||||
|
||||
/* Get the _mcount() call site out of LR */
|
||||
mflr r7
|
||||
/* Save it as pt_regs->nip */
|
||||
stw r7, _NIP(r1)
|
||||
/* Save the read LR in pt_regs->link */
|
||||
stw r0, _LINK(r1)
|
||||
|
||||
lis r3,function_trace_op@ha
|
||||
lwz r5,function_trace_op@l(r3)
|
||||
|
||||
/* Calculate ip from nip-4 into r3 for call below */
|
||||
subi r3, r7, MCOUNT_INSN_SIZE
|
||||
|
||||
/* Put the original return address in r4 as parent_ip */
|
||||
mr r4, r0
|
||||
|
||||
/* Save special regs */
|
||||
stw r8, _MSR(r1)
|
||||
stw r9, _CTR(r1)
|
||||
stw r10, _XER(r1)
|
||||
stw r11, _CCR(r1)
|
||||
|
||||
/* Load &pt_regs in r6 for call below */
|
||||
addi r6, r1, STACK_FRAME_OVERHEAD
|
||||
|
||||
/* ftrace_call(r3, r4, r5, r6) */
|
||||
.globl ftrace_regs_call
|
||||
ftrace_regs_call:
|
||||
bl ftrace_stub
|
||||
nop
|
||||
|
||||
/* Load ctr with the possibly modified NIP */
|
||||
lwz r3, _NIP(r1)
|
||||
mtctr r3
|
||||
|
||||
/* Restore gprs */
|
||||
lmw r2, GPR2(r1)
|
||||
|
||||
/* Restore possibly modified LR */
|
||||
lwz r0, _LINK(r1)
|
||||
mtlr r0
|
||||
|
||||
/* Pop our stack frame */
|
||||
addi r1, r1, INT_FRAME_SIZE
|
||||
|
||||
b ftrace_caller_common
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
_GLOBAL(ftrace_graph_caller)
|
||||
stwu r1,-48(r1)
|
||||
stw r3, 12(r1)
|
||||
stw r4, 16(r1)
|
||||
stw r5, 20(r1)
|
||||
stw r6, 24(r1)
|
||||
stw r7, 28(r1)
|
||||
stw r8, 32(r1)
|
||||
stw r9, 36(r1)
|
||||
stw r10,40(r1)
|
||||
|
||||
addi r5, r1, 48
|
||||
mfctr r4 /* ftrace_caller has moved local addr here */
|
||||
stw r4, 44(r1)
|
||||
mflr r3 /* ftrace_caller has restored LR from stack */
|
||||
subi r4, r4, MCOUNT_INSN_SIZE
|
||||
|
||||
bl prepare_ftrace_return
|
||||
nop
|
||||
|
||||
/*
|
||||
* prepare_ftrace_return gives us the address we divert to.
|
||||
* Change the LR in the callers stack frame to this.
|
||||
*/
|
||||
stw r3,52(r1)
|
||||
mtlr r3
|
||||
lwz r0,44(r1)
|
||||
mtctr r0
|
||||
|
||||
lwz r3, 12(r1)
|
||||
lwz r4, 16(r1)
|
||||
lwz r5, 20(r1)
|
||||
lwz r6, 24(r1)
|
||||
lwz r7, 28(r1)
|
||||
lwz r8, 32(r1)
|
||||
lwz r9, 36(r1)
|
||||
lwz r10,40(r1)
|
||||
|
||||
addi r1, r1, 48
|
||||
|
||||
bctr
|
||||
|
||||
_GLOBAL(return_to_handler)
|
||||
/* need to save return values */
|
||||
stwu r1, -32(r1)
|
||||
stw r3, 20(r1)
|
||||
stw r4, 16(r1)
|
||||
stw r31, 12(r1)
|
||||
mr r31, r1
|
||||
|
||||
bl ftrace_return_to_handler
|
||||
nop
|
||||
|
||||
/* return value has real return address */
|
||||
mtlr r3
|
||||
|
||||
lwz r3, 20(r1)
|
||||
lwz r4, 16(r1)
|
||||
lwz r31,12(r1)
|
||||
lwz r1, 0(r1)
|
||||
|
||||
/* Jump back to real return address */
|
||||
blr
|
||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
|
@ -10,6 +10,7 @@
|
|||
#include <asm/ppc-opcode.h>
|
||||
#include <asm/export.h>
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
.pushsection ".tramp.ftrace.text","aw",@progbits;
|
||||
.globl ftrace_tramp_text
|
||||
ftrace_tramp_text:
|
||||
|
@ -21,6 +22,7 @@ ftrace_tramp_text:
|
|||
ftrace_tramp_init:
|
||||
.space 64
|
||||
.popsection
|
||||
#endif
|
||||
|
||||
_GLOBAL(mcount)
|
||||
_GLOBAL(_mcount)
|
||||
|
@ -33,6 +35,7 @@ EXPORT_SYMBOL(_mcount)
|
|||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
_GLOBAL(return_to_handler)
|
||||
/* need to save return values */
|
||||
#ifdef CONFIG_PPC64
|
||||
std r4, -32(r1)
|
||||
std r3, -24(r1)
|
||||
/* save TOC */
|
||||
|
@ -46,6 +49,11 @@ _GLOBAL(return_to_handler)
|
|||
* Switch to our TOC to run inside the core kernel.
|
||||
*/
|
||||
ld r2, PACATOC(r13)
|
||||
#else
|
||||
stwu r1, -16(r1)
|
||||
stw r3, 8(r1)
|
||||
stw r4, 12(r1)
|
||||
#endif
|
||||
|
||||
bl ftrace_return_to_handler
|
||||
nop
|
||||
|
@ -53,11 +61,17 @@ _GLOBAL(return_to_handler)
|
|||
/* return value has real return address */
|
||||
mtlr r3
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
ld r1, 0(r1)
|
||||
ld r4, -32(r1)
|
||||
ld r3, -24(r1)
|
||||
ld r2, -16(r1)
|
||||
ld r31, -8(r1)
|
||||
#else
|
||||
lwz r3, 8(r1)
|
||||
lwz r4, 12(r1)
|
||||
addi r1, r1, 16
|
||||
#endif
|
||||
|
||||
/* Jump back to real return address */
|
||||
blr
|
|
@ -32,52 +32,71 @@
|
|||
* Our job is to save the register state into a struct pt_regs (on the stack)
|
||||
* and then arrange for the ftrace function to be called.
|
||||
*/
|
||||
_GLOBAL(ftrace_regs_caller)
|
||||
/* Save the original return address in A's stack frame */
|
||||
std r0,LRSAVE(r1)
|
||||
|
||||
.macro ftrace_regs_entry allregs
|
||||
/* Create our stack frame + pt_regs */
|
||||
stdu r1,-SWITCH_FRAME_SIZE(r1)
|
||||
PPC_STLU r1,-SWITCH_FRAME_SIZE(r1)
|
||||
|
||||
/* Save all gprs to pt_regs */
|
||||
SAVE_GPR(0, r1)
|
||||
SAVE_GPRS(2, 11, r1)
|
||||
SAVE_GPRS(3, 10, r1)
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
/* Save the original return address in A's stack frame */
|
||||
std r0, LRSAVE+SWITCH_FRAME_SIZE(r1)
|
||||
/* Ok to continue? */
|
||||
lbz r3, PACA_FTRACE_ENABLED(r13)
|
||||
cmpdi r3, 0
|
||||
beq ftrace_no_trace
|
||||
#endif
|
||||
|
||||
SAVE_GPRS(12, 31, r1)
|
||||
.if \allregs == 1
|
||||
SAVE_GPR(2, r1)
|
||||
SAVE_GPRS(11, 31, r1)
|
||||
.else
|
||||
#ifdef CONFIG_LIVEPATCH_64
|
||||
SAVE_GPR(14, r1)
|
||||
#endif
|
||||
.endif
|
||||
|
||||
/* Save previous stack pointer (r1) */
|
||||
addi r8, r1, SWITCH_FRAME_SIZE
|
||||
std r8, GPR1(r1)
|
||||
PPC_STL r8, GPR1(r1)
|
||||
|
||||
.if \allregs == 1
|
||||
/* Load special regs for save below */
|
||||
mfmsr r8
|
||||
mfctr r9
|
||||
mfxer r10
|
||||
mfcr r11
|
||||
.else
|
||||
/* Clear MSR to flag as ftrace_caller versus frace_regs_caller */
|
||||
li r8, 0
|
||||
.endif
|
||||
|
||||
/* Get the _mcount() call site out of LR */
|
||||
mflr r7
|
||||
/* Save it as pt_regs->nip */
|
||||
std r7, _NIP(r1)
|
||||
PPC_STL r7, _NIP(r1)
|
||||
/* Save the read LR in pt_regs->link */
|
||||
std r0, _LINK(r1)
|
||||
PPC_STL r0, _LINK(r1)
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
/* Save callee's TOC in the ABI compliant location */
|
||||
std r2, 24(r1)
|
||||
std r2, STK_GOT(r1)
|
||||
ld r2,PACATOC(r13) /* get kernel TOC in r2 */
|
||||
|
||||
addis r3,r2,function_trace_op@toc@ha
|
||||
addi r3,r3,function_trace_op@toc@l
|
||||
ld r5,0(r3)
|
||||
|
||||
#ifdef CONFIG_LIVEPATCH
|
||||
mr r14,r7 /* remember old NIP */
|
||||
#else
|
||||
lis r3,function_trace_op@ha
|
||||
lwz r5,function_trace_op@l(r3)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LIVEPATCH_64
|
||||
mr r14, r7 /* remember old NIP */
|
||||
#endif
|
||||
|
||||
/* Calculate ip from nip-4 into r3 for call below */
|
||||
subi r3, r7, MCOUNT_INSN_SIZE
|
||||
|
||||
|
@ -85,59 +104,77 @@ _GLOBAL(ftrace_regs_caller)
|
|||
mr r4, r0
|
||||
|
||||
/* Save special regs */
|
||||
std r8, _MSR(r1)
|
||||
std r9, _CTR(r1)
|
||||
std r10, _XER(r1)
|
||||
std r11, _CCR(r1)
|
||||
PPC_STL r8, _MSR(r1)
|
||||
.if \allregs == 1
|
||||
PPC_STL r9, _CTR(r1)
|
||||
PPC_STL r10, _XER(r1)
|
||||
PPC_STL r11, _CCR(r1)
|
||||
.endif
|
||||
|
||||
/* Load &pt_regs in r6 for call below */
|
||||
addi r6, r1 ,STACK_FRAME_OVERHEAD
|
||||
addi r6, r1, STACK_FRAME_OVERHEAD
|
||||
.endm
|
||||
|
||||
.macro ftrace_regs_exit allregs
|
||||
/* Load ctr with the possibly modified NIP */
|
||||
PPC_LL r3, _NIP(r1)
|
||||
mtctr r3
|
||||
|
||||
#ifdef CONFIG_LIVEPATCH_64
|
||||
cmpd r14, r3 /* has NIP been altered? */
|
||||
#endif
|
||||
|
||||
/* Restore gprs */
|
||||
.if \allregs == 1
|
||||
REST_GPRS(2, 31, r1)
|
||||
.else
|
||||
REST_GPRS(3, 10, r1)
|
||||
#ifdef CONFIG_LIVEPATCH_64
|
||||
REST_GPR(14, r1)
|
||||
#endif
|
||||
.endif
|
||||
|
||||
/* Restore possibly modified LR */
|
||||
PPC_LL r0, _LINK(r1)
|
||||
mtlr r0
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
/* Restore callee's TOC */
|
||||
ld r2, STK_GOT(r1)
|
||||
#endif
|
||||
|
||||
/* Pop our stack frame */
|
||||
addi r1, r1, SWITCH_FRAME_SIZE
|
||||
|
||||
#ifdef CONFIG_LIVEPATCH_64
|
||||
/* Based on the cmpd above, if the NIP was altered handle livepatch */
|
||||
bne- livepatch_handler
|
||||
#endif
|
||||
bctr /* jump after _mcount site */
|
||||
.endm
|
||||
|
||||
_GLOBAL(ftrace_regs_caller)
|
||||
ftrace_regs_entry 1
|
||||
/* ftrace_call(r3, r4, r5, r6) */
|
||||
.globl ftrace_regs_call
|
||||
ftrace_regs_call:
|
||||
bl ftrace_stub
|
||||
nop
|
||||
ftrace_regs_exit 1
|
||||
|
||||
/* Load ctr with the possibly modified NIP */
|
||||
ld r3, _NIP(r1)
|
||||
mtctr r3
|
||||
#ifdef CONFIG_LIVEPATCH
|
||||
cmpd r14, r3 /* has NIP been altered? */
|
||||
#endif
|
||||
|
||||
/* Restore gprs */
|
||||
REST_GPR(0, r1)
|
||||
REST_GPRS(2, 31, r1)
|
||||
|
||||
/* Restore possibly modified LR */
|
||||
ld r0, _LINK(r1)
|
||||
mtlr r0
|
||||
|
||||
/* Restore callee's TOC */
|
||||
ld r2, 24(r1)
|
||||
|
||||
/* Pop our stack frame */
|
||||
addi r1, r1, SWITCH_FRAME_SIZE
|
||||
|
||||
#ifdef CONFIG_LIVEPATCH
|
||||
/* Based on the cmpd above, if the NIP was altered handle livepatch */
|
||||
bne- livepatch_handler
|
||||
#endif
|
||||
|
||||
ftrace_caller_common:
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
.globl ftrace_graph_call
|
||||
ftrace_graph_call:
|
||||
b ftrace_graph_stub
|
||||
_GLOBAL(ftrace_graph_stub)
|
||||
#endif
|
||||
|
||||
bctr /* jump after _mcount site */
|
||||
_GLOBAL(ftrace_caller)
|
||||
ftrace_regs_entry 0
|
||||
/* ftrace_call(r3, r4, r5, r6) */
|
||||
.globl ftrace_call
|
||||
ftrace_call:
|
||||
bl ftrace_stub
|
||||
nop
|
||||
ftrace_regs_exit 0
|
||||
|
||||
_GLOBAL(ftrace_stub)
|
||||
blr
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
ftrace_no_trace:
|
||||
mflr r3
|
||||
mtctr r3
|
||||
|
@ -145,68 +182,9 @@ ftrace_no_trace:
|
|||
addi r1, r1, SWITCH_FRAME_SIZE
|
||||
mtlr r0
|
||||
bctr
|
||||
#endif
|
||||
|
||||
_GLOBAL(ftrace_caller)
|
||||
/* Save the original return address in A's stack frame */
|
||||
std r0, LRSAVE(r1)
|
||||
|
||||
/* Create our stack frame + pt_regs */
|
||||
stdu r1, -SWITCH_FRAME_SIZE(r1)
|
||||
|
||||
/* Save all gprs to pt_regs */
|
||||
SAVE_GPRS(3, 10, r1)
|
||||
|
||||
lbz r3, PACA_FTRACE_ENABLED(r13)
|
||||
cmpdi r3, 0
|
||||
beq ftrace_no_trace
|
||||
|
||||
/* Get the _mcount() call site out of LR */
|
||||
mflr r7
|
||||
std r7, _NIP(r1)
|
||||
|
||||
/* Save callee's TOC in the ABI compliant location */
|
||||
std r2, 24(r1)
|
||||
ld r2, PACATOC(r13) /* get kernel TOC in r2 */
|
||||
|
||||
addis r3, r2, function_trace_op@toc@ha
|
||||
addi r3, r3, function_trace_op@toc@l
|
||||
ld r5, 0(r3)
|
||||
|
||||
/* Calculate ip from nip-4 into r3 for call below */
|
||||
subi r3, r7, MCOUNT_INSN_SIZE
|
||||
|
||||
/* Put the original return address in r4 as parent_ip */
|
||||
mr r4, r0
|
||||
|
||||
/* Set pt_regs to NULL */
|
||||
li r6, 0
|
||||
|
||||
/* ftrace_call(r3, r4, r5, r6) */
|
||||
.globl ftrace_call
|
||||
ftrace_call:
|
||||
bl ftrace_stub
|
||||
nop
|
||||
|
||||
ld r3, _NIP(r1)
|
||||
mtctr r3
|
||||
|
||||
/* Restore gprs */
|
||||
REST_GPRS(3, 10, r1)
|
||||
|
||||
/* Restore callee's TOC */
|
||||
ld r2, 24(r1)
|
||||
|
||||
/* Pop our stack frame */
|
||||
addi r1, r1, SWITCH_FRAME_SIZE
|
||||
|
||||
/* Reload original LR */
|
||||
ld r0, LRSAVE(r1)
|
||||
mtlr r0
|
||||
|
||||
/* Handle function_graph or go back */
|
||||
b ftrace_caller_common
|
||||
|
||||
#ifdef CONFIG_LIVEPATCH
|
||||
#ifdef CONFIG_LIVEPATCH_64
|
||||
/*
|
||||
* This function runs in the mcount context, between two functions. As
|
||||
* such it can only clobber registers which are volatile and used in
|
||||
|
@ -273,55 +251,3 @@ livepatch_handler:
|
|||
/* Return to original caller of live patched function */
|
||||
blr
|
||||
#endif /* CONFIG_LIVEPATCH */
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
_GLOBAL(ftrace_graph_caller)
|
||||
stdu r1, -112(r1)
|
||||
/* with -mprofile-kernel, parameter regs are still alive at _mcount */
|
||||
std r10, 104(r1)
|
||||
std r9, 96(r1)
|
||||
std r8, 88(r1)
|
||||
std r7, 80(r1)
|
||||
std r6, 72(r1)
|
||||
std r5, 64(r1)
|
||||
std r4, 56(r1)
|
||||
std r3, 48(r1)
|
||||
|
||||
/* Save callee's TOC in the ABI compliant location */
|
||||
std r2, 24(r1)
|
||||
ld r2, PACATOC(r13) /* get kernel TOC in r2 */
|
||||
|
||||
addi r5, r1, 112
|
||||
mfctr r4 /* ftrace_caller has moved local addr here */
|
||||
std r4, 40(r1)
|
||||
mflr r3 /* ftrace_caller has restored LR from stack */
|
||||
subi r4, r4, MCOUNT_INSN_SIZE
|
||||
|
||||
bl prepare_ftrace_return
|
||||
nop
|
||||
|
||||
/*
|
||||
* prepare_ftrace_return gives us the address we divert to.
|
||||
* Change the LR to this.
|
||||
*/
|
||||
mtlr r3
|
||||
|
||||
ld r0, 40(r1)
|
||||
mtctr r0
|
||||
ld r10, 104(r1)
|
||||
ld r9, 96(r1)
|
||||
ld r8, 88(r1)
|
||||
ld r7, 80(r1)
|
||||
ld r6, 72(r1)
|
||||
ld r5, 64(r1)
|
||||
ld r4, 56(r1)
|
||||
ld r3, 48(r1)
|
||||
|
||||
/* Restore callee's TOC */
|
||||
ld r2, 24(r1)
|
||||
|
||||
addi r1, r1, 112
|
||||
mflr r0
|
||||
std r0, LRSAVE(r1)
|
||||
bctr
|
||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
|
@ -1,3 +1,5 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
vdso32.lds
|
||||
vdso32.so.dbg
|
||||
vdso64.lds
|
||||
vdso64.so.dbg
|
|
@ -0,0 +1,103 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
# List of files in the vdso, has to be asm only for now
|
||||
|
||||
ARCH_REL_TYPE_ABS := R_PPC_JUMP_SLOT|R_PPC_GLOB_DAT|R_PPC_ADDR32|R_PPC_ADDR24|R_PPC_ADDR16|R_PPC_ADDR16_LO|R_PPC_ADDR16_HI|R_PPC_ADDR16_HA|R_PPC_ADDR14|R_PPC_ADDR14_BRTAKEN|R_PPC_ADDR14_BRNTAKEN|R_PPC_REL24
|
||||
include $(srctree)/lib/vdso/Makefile
|
||||
|
||||
obj-vdso32 = sigtramp32-32.o gettimeofday-32.o datapage-32.o cacheflush-32.o note-32.o getcpu-32.o
|
||||
obj-vdso64 = sigtramp64-64.o gettimeofday-64.o datapage-64.o cacheflush-64.o note-64.o getcpu-64.o
|
||||
|
||||
ifneq ($(c-gettimeofday-y),)
|
||||
CFLAGS_vgettimeofday-32.o += -include $(c-gettimeofday-y)
|
||||
CFLAGS_vgettimeofday-32.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
|
||||
CFLAGS_vgettimeofday-32.o += $(call cc-option, -fno-stack-protector)
|
||||
CFLAGS_vgettimeofday-32.o += -DDISABLE_BRANCH_PROFILING
|
||||
CFLAGS_vgettimeofday-32.o += -ffreestanding -fasynchronous-unwind-tables
|
||||
CFLAGS_REMOVE_vgettimeofday-32.o = $(CC_FLAGS_FTRACE)
|
||||
CFLAGS_REMOVE_vgettimeofday-32.o += -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc
|
||||
CFLAGS_vgettimeofday-64.o += -include $(c-gettimeofday-y)
|
||||
CFLAGS_vgettimeofday-64.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
|
||||
CFLAGS_vgettimeofday-64.o += $(call cc-option, -fno-stack-protector)
|
||||
CFLAGS_vgettimeofday-64.o += -DDISABLE_BRANCH_PROFILING
|
||||
CFLAGS_vgettimeofday-64.o += -ffreestanding -fasynchronous-unwind-tables
|
||||
CFLAGS_REMOVE_vgettimeofday-64.o = $(CC_FLAGS_FTRACE)
|
||||
# Go prior to 1.16.x assumes r30 is not clobbered by any VDSO code. That used to be true
|
||||
# by accident when the VDSO was hand-written asm code, but may not be now that the VDSO is
|
||||
# compiler generated. To avoid breaking Go tell GCC not to use r30. Impact on code
|
||||
# generation is minimal, it will just use r29 instead.
|
||||
CFLAGS_vgettimeofday-64.o += $(call cc-option, -ffixed-r30)
|
||||
endif
|
||||
|
||||
# Build rules
|
||||
|
||||
ifdef CROSS32_COMPILE
|
||||
VDSOCC := $(CROSS32_COMPILE)gcc
|
||||
else
|
||||
VDSOCC := $(CC)
|
||||
endif
|
||||
|
||||
targets := $(obj-vdso32) vdso32.so.dbg vgettimeofday-32.o
|
||||
obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32))
|
||||
targets += $(obj-vdso64) vdso64.so.dbg vgettimeofday-64.o
|
||||
obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64))
|
||||
|
||||
GCOV_PROFILE := n
|
||||
KCOV_INSTRUMENT := n
|
||||
UBSAN_SANITIZE := n
|
||||
KASAN_SANITIZE := n
|
||||
|
||||
ccflags-y := -shared -fno-common -fno-builtin -nostdlib -Wl,--hash-style=both
|
||||
|
||||
CC32FLAGS := -Wl,-soname=linux-vdso32.so.1 -m32
|
||||
AS32FLAGS := -D__VDSO32__ -s
|
||||
|
||||
CC64FLAGS := -Wl,-soname=linux-vdso64.so.1
|
||||
AS64FLAGS := -D__VDSO64__ -s
|
||||
|
||||
targets += vdso32.lds
|
||||
CPPFLAGS_vdso32.lds += -P -C -Upowerpc
|
||||
targets += vdso64.lds
|
||||
CPPFLAGS_vdso64.lds += -P -C -U$(ARCH)
|
||||
|
||||
# link rule for the .so file, .lds has to be first
|
||||
$(obj)/vdso32.so.dbg: $(src)/vdso32.lds $(obj-vdso32) $(obj)/vgettimeofday-32.o FORCE
|
||||
$(call if_changed,vdso32ld_and_check)
|
||||
$(obj)/vdso64.so.dbg: $(src)/vdso64.lds $(obj-vdso64) $(obj)/vgettimeofday-64.o FORCE
|
||||
$(call if_changed,vdso64ld_and_check)
|
||||
|
||||
# assembly rules for the .S files
|
||||
$(obj-vdso32): %-32.o: %.S FORCE
|
||||
$(call if_changed_dep,vdso32as)
|
||||
$(obj)/vgettimeofday-32.o: %-32.o: %.c FORCE
|
||||
$(call if_changed_dep,vdso32cc)
|
||||
$(obj-vdso64): %-64.o: %.S FORCE
|
||||
$(call if_changed_dep,vdso64as)
|
||||
$(obj)/vgettimeofday-64.o: %-64.o: %.c FORCE
|
||||
$(call if_changed_dep,cc_o_c)
|
||||
|
||||
# Generate VDSO offsets using helper script
|
||||
gen-vdso32sym := $(srctree)/$(src)/gen_vdso32_offsets.sh
|
||||
quiet_cmd_vdso32sym = VDSO32SYM $@
|
||||
cmd_vdso32sym = $(NM) $< | $(gen-vdso32sym) | LC_ALL=C sort > $@
|
||||
gen-vdso64sym := $(srctree)/$(src)/gen_vdso64_offsets.sh
|
||||
quiet_cmd_vdso64sym = VDSO64SYM $@
|
||||
cmd_vdso64sym = $(NM) $< | $(gen-vdso64sym) | LC_ALL=C sort > $@
|
||||
|
||||
include/generated/vdso32-offsets.h: $(obj)/vdso32.so.dbg FORCE
|
||||
$(call if_changed,vdso32sym)
|
||||
include/generated/vdso64-offsets.h: $(obj)/vdso64.so.dbg FORCE
|
||||
$(call if_changed,vdso64sym)
|
||||
|
||||
# actual build commands
|
||||
quiet_cmd_vdso32ld_and_check = VDSO32L $@
|
||||
cmd_vdso32ld_and_check = $(VDSOCC) $(c_flags) $(CC32FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) ; $(cmd_vdso_check)
|
||||
quiet_cmd_vdso32as = VDSO32A $@
|
||||
cmd_vdso32as = $(VDSOCC) $(a_flags) $(CC32FLAGS) $(AS32FLAGS) -c -o $@ $<
|
||||
quiet_cmd_vdso32cc = VDSO32C $@
|
||||
cmd_vdso32cc = $(VDSOCC) $(c_flags) $(CC32FLAGS) -c -o $@ $<
|
||||
|
||||
quiet_cmd_vdso64ld_and_check = VDSO64L $@
|
||||
cmd_vdso64ld_and_check = $(VDSOCC) $(c_flags) $(CC64FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) ; $(cmd_vdso_check)
|
||||
quiet_cmd_vdso64as = VDSO64A $@
|
||||
cmd_vdso64as = $(VDSOCC) $(a_flags) $(CC64FLAGS) $(AS64FLAGS) -c -o $@ $<
|
|
@ -46,7 +46,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
|
|||
add r8,r8,r5 /* ensure we get enough */
|
||||
#ifdef CONFIG_PPC64
|
||||
lwz r9,CFG_DCACHE_LOGBLOCKSZ(r10)
|
||||
srw. r8,r8,r9 /* compute line count */
|
||||
PPC_SRL. r8,r8,r9 /* compute line count */
|
||||
#else
|
||||
srwi. r8, r8, L1_CACHE_SHIFT
|
||||
mr r7, r6
|
||||
|
@ -72,7 +72,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
|
|||
subf r8,r6,r4 /* compute length */
|
||||
add r8,r8,r5
|
||||
lwz r9,CFG_ICACHE_LOGBLOCKSZ(r10)
|
||||
srw. r8,r8,r9 /* compute line count */
|
||||
PPC_SRL. r8,r8,r9 /* compute line count */
|
||||
crclr cr0*4+so
|
||||
beqlr /* nothing to do? */
|
||||
#endif
|
|
@ -30,11 +30,15 @@ V_FUNCTION_BEGIN(__kernel_get_syscall_map)
|
|||
mr. r4,r3
|
||||
get_datapage r3
|
||||
mtlr r12
|
||||
#ifdef __powerpc64__
|
||||
addi r3,r3,CFG_SYSCALL_MAP64
|
||||
#else
|
||||
addi r3,r3,CFG_SYSCALL_MAP32
|
||||
#endif
|
||||
crclr cr0*4+so
|
||||
beqlr
|
||||
li r0,NR_syscalls
|
||||
stw r0,0(r4)
|
||||
crclr cr0*4+so
|
||||
blr
|
||||
.cfi_endproc
|
||||
V_FUNCTION_END(__kernel_get_syscall_map)
|
||||
|
@ -49,8 +53,10 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq)
|
|||
mflr r12
|
||||
.cfi_register lr,r12
|
||||
get_datapage r3
|
||||
#ifndef __powerpc64__
|
||||
lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3)
|
||||
lwz r3,CFG_TB_TICKS_PER_SEC(r3)
|
||||
#endif
|
||||
PPC_LL r3,CFG_TB_TICKS_PER_SEC(r3)
|
||||
mtlr r12
|
||||
crclr cr0*4+so
|
||||
blr
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue