Commit 1f1c153e authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 9a8b3d5f fe2640bd
......@@ -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.
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.*
......
// 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 @@ &seville_port0 {
managed = "in-band-status";
phy-handle = <&phy_qsgmii_0>;
phy-mode = "qsgmii";
label = "ETH5";
label = "ETH3";
status = "okay";
};
......@@ -135,7 +135,7 @@ &seville_port2 {
managed = "in-band-status";
phy-handle = <&phy_qsgmii_2>;
phy-mode = "qsgmii";
label = "ETH7";
label = "ETH5";
status = "okay";
};
......@@ -151,7 +151,7 @@ &seville_port4 {
managed = "in-band-status";
phy-handle = <&phy_qsgmii_4>;
phy-mode = "qsgmii";
label = "ETH9";
label = "ETH7";
status = "okay";
};
......@@ -167,7 +167,7 @@ &seville_port6 {
managed = "in-band-status";
phy-handle = <&phy_qsgmii_6>;
phy-mode = "qsgmii";
label = "ETH11";
label = "ETH9";
status = "okay";
};
......
......@@ -139,12 +139,12 @@ pca9546@77 {
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 @@ rtc@68 {
reg = <0x68>;
};
dtt@48 {
dtt@34 {
compatible = "maxim,max1237";
reg = <0x34>;
};
......
......@@ -136,7 +136,7 @@ rtc@68 {
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
#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
#ifndef __ASSEMBLY__
#include <asm/page.h>
#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_disable_ftrace_graph_caller(void)
int ftrace_enable_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_ftrace_graph_caller(true);
}
return ftrace_modify_code(ip, old, new);
int ftrace_disable_ftrace_graph_caller(void)
{
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(&current->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
......
/* 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)
#else
lis r3,function_trace_op@ha
lwz r5,function_trace_op@l(r3)
#endif
#ifdef CONFIG_LIVEPATCH
mr r14,r7 /* remember old NIP */
#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,128 +104,87 @@ _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
/* ftrace_call(r3, r4, r5, r6) */
.globl ftrace_regs_call
ftrace_regs_call:
bl ftrace_stub
nop
addi r6, r1, STACK_FRAME_OVERHEAD
.endm
.macro ftrace_regs_exit allregs
/* Load ctr with the possibly modified NIP */
ld r3, _NIP(r1)
PPC_LL r3, _NIP(r1)
mtctr r3
#ifdef CONFIG_LIVEPATCH
#ifdef CONFIG_LIVEPATCH_64
cmpd r14, r3 /* has NIP been altered? */
#endif
/* Restore gprs */
REST_GPR(0, r1)
.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 */
ld r0, _LINK(r1)
PPC_LL r0, _LINK(r1)
mtlr r0
#ifdef CONFIG_PPC64
/* Restore callee's TOC */
ld r2, 24(r1)
ld r2, STK_GOT(r1)
#endif
/* Pop our stack frame */
addi r1, r1, SWITCH_FRAME_SIZE
#ifdef CONFIG_LIVEPATCH
#ifdef CONFIG_LIVEPATCH_64
/* 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 */
.endm
_GLOBAL(ftrace_stub)
blr
ftrace_no_trace:
mflr r3
mtctr r3
REST_GPR(3, r1)
addi r1, r1, SWITCH_FRAME_SIZE
mtlr r0
bctr
_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
_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_regs_entry 0
/* ftrace_call(r3, r4, r5, r6) */
.globl ftrace_call
ftrace_call:
bl ftrace_stub
nop
ftrace_regs_exit 0
ld r3, _NIP(r1)
mtctr r3
/* Restore gprs */
REST_GPRS(3, 10, r1)
/* Restore callee's TOC */
ld r2, 24(r1)
_GLOBAL(ftrace_stub)
blr
/* Pop our stack frame */
#ifdef CONFIG_PPC64
ftrace_no_trace:
mflr r3
mtctr r3
REST_GPR(3, r1)
addi r1, r1, SWITCH_FRAME_SIZE
/* Reload original LR */
ld r0, LRSAVE(r1)
mtlr r0
bctr
#endif
/* 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 */
# SPDX-License-Identifier: GPL-2.0-only
vdso32.lds
vdso32.so.dbg
vdso64.lds
vdso64.so.dbg
......@@ -5,15 +5,28 @@
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 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o getcpu.o
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.o += -include $(c-gettimeofday-y)
CFLAGS_vgettimeofday.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
CFLAGS_vgettimeofday.o += $(call cc-option, -fno-stack-protector)
CFLAGS_vgettimeofday.o += -DDISABLE_BRANCH_PROFILING
CFLAGS_vgettimeofday.o += -ffreestanding -fasynchronous-unwind-tables
CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE)
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
......@@ -24,50 +37,67 @@ else
VDSOCC := $(CC)
endif
CC32FLAGS :=
ifdef CONFIG_PPC64
CC32FLAGS += -m32
KBUILD_CFLAGS := $(filter-out -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc,$(KBUILD_CFLAGS))
endif
targets := $(obj-vdso32) vdso32.so.dbg vgettimeofday.o
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,-soname=linux-vdso32.so.1 -Wl,--hash-style=both
asflags-y := -D__VDSO32__ -s
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
obj-y += vdso32_wrapper.o
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.o FORCE
$(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): %.o: %.S FORCE
$(obj-vdso32): %-32.o: %.S FORCE
$(call if_changed_dep,vdso32as)
$(obj)/vgettimeofday.o: %.o: %.c FORCE
$(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-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh
quiet_cmd_vdsosym = VDSOSYM $@
cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@
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,vdsosym)
$(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) -c -o $@ $<
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
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment