Skip to content

Commit

Permalink
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/upstream-…
Browse files Browse the repository at this point in the history
…linus

* 'upstream' of git://git.linux-mips.org/pub/scm/upstream-linus: (26 commits)
  MIPS: Alchemy: Fix reset for MTX-1 and XXS1500
  MIPS: MTX-1: Make au1000_eth probe all PHY addresses
  MIPS: Jz4740: Add HAVE_CLK
  MIPS: Move idle task creation to work queue
  MIPS, Perf-events: Use unsigned delta for right shift in event update
  MIPS, Perf-events: Work with the new callchain interface
  MIPS, Perf-events: Fix event check in validate_event()
  MIPS, Perf-events: Work with the new PMU interface
  MIPS, Perf-events: Work with irq_work
  MIPS: Fix always CONFIG_LOONGSON_UART_BASE=y
  MIPS: Loongson: Fix potentially wrong string handling
  MIPS: Fix GCC-4.6 'set but not used' warning in arch/mips/mm/init.c
  MIPS: Fix GCC-4.6 'set but not used' warning in ieee754int.h
  MIPS: Remove unused code from arch/mips/kernel/syscall.c
  MIPS: Fix GCC-4.6 'set but not used' warning in signal*.c
  MIPS: MSP: Fix MSP71xx bpci interrupt handler return value
  MIPS: Select R4K timer lib for all MSP platforms
  MIPS: Loongson: Remove ad-hoc cmdline default
  MIPS: Clear the correct flag in sysmips(MIPS_FIXADE, ...).
  MIPS: Add an unreachable return statement to satisfy buggy GCCs.
  ...
  • Loading branch information
torvalds committed Mar 14, 2011
2 parents 869c34f + 9ced975 commit 2990821
Show file tree
Hide file tree
Showing 22 changed files with 331 additions and 305 deletions.
4 changes: 4 additions & 0 deletions arch/mips/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ config MIPS
select HAVE_GENERIC_DMA_COHERENT
select HAVE_IDE
select HAVE_OPROFILE
select HAVE_IRQ_WORK
select HAVE_PERF_EVENTS
select PERF_USE_VMALLOC
select HAVE_ARCH_KGDB
Expand Down Expand Up @@ -208,6 +209,7 @@ config MACH_JZ4740
select ARCH_REQUIRE_GPIOLIB
select SYS_HAS_EARLY_PRINTK
select HAVE_PWM
select HAVE_CLK

config LASAT
bool "LASAT Networks platforms"
Expand Down Expand Up @@ -333,6 +335,8 @@ config PNX8550_STB810
config PMC_MSP
bool "PMC-Sierra MSP chipsets"
depends on EXPERIMENTAL
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
select SWAP_IO_SPACE
select NO_EXCEPT_FILL
Expand Down
4 changes: 2 additions & 2 deletions arch/mips/alchemy/mtx-1/board_setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ int mtx1_pci_idsel(unsigned int devsel, int assert);

static void mtx1_reset(char *c)
{
/* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
au_writel(0x00000000, 0xAE00001C);
/* Jump to the reset vector */
__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
}

static void mtx1_power_off(void)
Expand Down
9 changes: 9 additions & 0 deletions arch/mips/alchemy/mtx-1/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include <linux/mtd/physmap.h>
#include <mtd/mtd-abi.h>

#include <asm/mach-au1x00/au1xxx_eth.h>

static struct gpio_keys_button mtx1_gpio_button[] = {
{
.gpio = 207,
Expand Down Expand Up @@ -140,10 +142,17 @@ static struct __initdata platform_device * mtx1_devs[] = {
&mtx1_mtd,
};

static struct au1000_eth_platform_data mtx1_au1000_eth0_pdata = {
.phy_search_highest_addr = 1,
.phy1_search_mac0 = 1,
};

static int __init mtx1_register_devices(void)
{
int rc;

au1xxx_override_eth_cfg(0, &mtx1_au1000_eth0_pdata);

rc = gpio_request(mtx1_gpio_button[0].gpio,
mtx1_gpio_button[0].desc);
if (rc < 0) {
Expand Down
4 changes: 2 additions & 2 deletions arch/mips/alchemy/xxs1500/board_setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@

static void xxs1500_reset(char *c)
{
/* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
au_writel(0x00000000, 0xAE00001C);
/* Jump to the reset vector */
__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
}

static void xxs1500_power_off(void)
Expand Down
12 changes: 1 addition & 11 deletions arch/mips/include/asm/perf_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,5 @@

#ifndef __MIPS_PERF_EVENT_H__
#define __MIPS_PERF_EVENT_H__

/*
* MIPS performance counters do not raise NMI upon overflow, a regular
* interrupt will be signaled. Hence we can do the pending perf event
* work at the tail of the irq handler.
*/
static inline void
set_perf_event_pending(void)
{
}

/* Leave it empty here. The file is required by linux/perf_event.h */
#endif /* __MIPS_PERF_EVENT_H__ */
179 changes: 95 additions & 84 deletions arch/mips/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,13 @@
#include <asm/cacheflush.h>
#include <asm/uasm.h>

/*
* If the Instruction Pointer is in module space (0xc0000000), return true;
* otherwise, it is in kernel space (0x80000000), return false.
*
* FIXME: This will not work when the kernel space and module space are the
* same. If they are the same, we need to modify scripts/recordmcount.pl,
* ftrace_make_nop/call() and the other related parts to ensure the
* enabling/disabling of the calling site to _mcount is right for both kernel
* and module.
*/

static inline int in_module(unsigned long ip)
{
return ip & 0x40000000;
}
#include <asm-generic/sections.h>

#ifdef CONFIG_DYNAMIC_FTRACE

#define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */
#define ADDR_MASK 0x03ffffff /* op_code|addr : 31...26|25 ....0 */

#define INSN_B_1F_4 0x10000004 /* b 1f; offset = 4 */
#define INSN_B_1F_5 0x10000005 /* b 1f; offset = 5 */
#define INSN_NOP 0x00000000 /* nop */
#define INSN_JAL(addr) \
((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK)))
Expand Down Expand Up @@ -69,6 +53,20 @@ static inline void ftrace_dyn_arch_init_insns(void)
#endif
}

/*
* Check if the address is in kernel space
*
* Clone core_kernel_text() from kernel/extable.c, but doesn't call
* init_kernel_text() for Ftrace doesn't trace functions in init sections.
*/
static inline int in_kernel_space(unsigned long ip)
{
if (ip >= (unsigned long)_stext &&
ip <= (unsigned long)_etext)
return 1;
return 0;
}

static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
{
int faulted;
Expand All @@ -84,46 +82,54 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
return 0;
}

/*
* The details about the calling site of mcount on MIPS
*
* 1. For kernel:
*
* move at, ra
* jal _mcount --> nop
*
* 2. For modules:
*
* 2.1 For KBUILD_MCOUNT_RA_ADDRESS and CONFIG_32BIT
*
* lui v1, hi_16bit_of_mcount --> b 1f (0x10000005)
* addiu v1, v1, low_16bit_of_mcount
* move at, ra
* move $12, ra_address
* jalr v1
* sub sp, sp, 8
* 1: offset = 5 instructions
* 2.2 For the Other situations
*
* lui v1, hi_16bit_of_mcount --> b 1f (0x10000004)
* addiu v1, v1, low_16bit_of_mcount
* move at, ra
* jalr v1
* nop | move $12, ra_address | sub sp, sp, 8
* 1: offset = 4 instructions
*/

#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT)
#define MCOUNT_OFFSET_INSNS 5
#else
#define MCOUNT_OFFSET_INSNS 4
#endif
#define INSN_B_1F (0x10000000 | MCOUNT_OFFSET_INSNS)

int ftrace_make_nop(struct module *mod,
struct dyn_ftrace *rec, unsigned long addr)
{
unsigned int new;
unsigned long ip = rec->ip;

/*
* We have compiled module with -mlong-calls, but compiled the kernel
* without it, we need to cope with them respectively.
* If ip is in kernel space, no long call, otherwise, long call is
* needed.
*/
if (in_module(ip)) {
#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT)
/*
* lui v1, hi_16bit_of_mcount --> b 1f (0x10000005)
* addiu v1, v1, low_16bit_of_mcount
* move at, ra
* move $12, ra_address
* jalr v1
* sub sp, sp, 8
* 1: offset = 5 instructions
*/
new = INSN_B_1F_5;
#else
/*
* lui v1, hi_16bit_of_mcount --> b 1f (0x10000004)
* addiu v1, v1, low_16bit_of_mcount
* move at, ra
* jalr v1
* nop | move $12, ra_address | sub sp, sp, 8
* 1: offset = 4 instructions
*/
new = INSN_B_1F_4;
#endif
} else {
/*
* move at, ra
* jal _mcount --> nop
*/
new = INSN_NOP;
}
new = in_kernel_space(ip) ? INSN_NOP : INSN_B_1F;

return ftrace_modify_code(ip, new);
}

Expand All @@ -132,8 +138,8 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
unsigned int new;
unsigned long ip = rec->ip;

/* ip, module: 0xc0000000, kernel: 0x80000000 */
new = in_module(ip) ? insn_lui_v1_hi16_mcount : insn_jal_ftrace_caller;
new = in_kernel_space(ip) ? insn_jal_ftrace_caller :
insn_lui_v1_hi16_mcount;

return ftrace_modify_code(ip, new);
}
Expand Down Expand Up @@ -190,29 +196,25 @@ int ftrace_disable_ftrace_graph_caller(void)
#define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */
#define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */

unsigned long ftrace_get_parent_addr(unsigned long self_addr,
unsigned long parent,
unsigned long parent_addr,
unsigned long fp)
unsigned long ftrace_get_parent_ra_addr(unsigned long self_ra, unsigned long
old_parent_ra, unsigned long parent_ra_addr, unsigned long fp)
{
unsigned long sp, ip, ra;
unsigned long sp, ip, tmp;
unsigned int code;
int faulted;

/*
* For module, move the ip from calling site of mcount to the
* instruction "lui v1, hi_16bit_of_mcount"(offset is 20), but for
* kernel, move to the instruction "move ra, at"(offset is 12)
* For module, move the ip from the return address after the
* instruction "lui v1, hi_16bit_of_mcount"(offset is 24), but for
* kernel, move after the instruction "move ra, at"(offset is 16)
*/
ip = self_addr - (in_module(self_addr) ? 20 : 12);
ip = self_ra - (in_kernel_space(self_ra) ? 16 : 24);

/*
* search the text until finding the non-store instruction or "s{d,w}
* ra, offset(sp)" instruction
*/
do {
ip -= 4;

/* get the code at "ip": code = *(unsigned int *)ip; */
safe_load_code(code, ip, faulted);

Expand All @@ -224,18 +226,20 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr,
* store the ra on the stack
*/
if ((code & S_R_SP) != S_R_SP)
return parent_addr;
return parent_ra_addr;

} while (((code & S_RA_SP) != S_RA_SP));
/* Move to the next instruction */
ip -= 4;
} while ((code & S_RA_SP) != S_RA_SP);

sp = fp + (code & OFFSET_MASK);

/* ra = *(unsigned long *)sp; */
safe_load_stack(ra, sp, faulted);
/* tmp = *(unsigned long *)sp; */
safe_load_stack(tmp, sp, faulted);
if (unlikely(faulted))
return 0;

if (ra == parent)
if (tmp == old_parent_ra)
return sp;
return 0;
}
Expand All @@ -246,21 +250,21 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr,
* Hook the return address and push it in the stack of return addrs
* in current thread info.
*/
void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra,
unsigned long fp)
{
unsigned long old;
unsigned long old_parent_ra;
struct ftrace_graph_ent trace;
unsigned long return_hooker = (unsigned long)
&return_to_handler;
int faulted;
int faulted, insns;

if (unlikely(atomic_read(&current->tracing_graph_pause)))
return;

/*
* "parent" is the stack address saved the return address of the caller
* of _mcount.
* "parent_ra_addr" is the stack address saved the return address of
* the caller of _mcount.
*
* if the gcc < 4.5, a leaf function does not save the return address
* in the stack address, so, we "emulate" one in _mcount's stack space,
Expand All @@ -275,37 +279,44 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
* do it in ftrace_graph_caller of mcount.S.
*/

/* old = *parent; */
safe_load_stack(old, parent, faulted);
/* old_parent_ra = *parent_ra_addr; */
safe_load_stack(old_parent_ra, parent_ra_addr, faulted);
if (unlikely(faulted))
goto out;
#ifndef KBUILD_MCOUNT_RA_ADDRESS
parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old,
(unsigned long)parent, fp);
parent_ra_addr = (unsigned long *)ftrace_get_parent_ra_addr(self_ra,
old_parent_ra, (unsigned long)parent_ra_addr, fp);
/*
* If fails when getting the stack address of the non-leaf function's
* ra, stop function graph tracer and return
*/
if (parent == 0)
if (parent_ra_addr == 0)
goto out;
#endif
/* *parent = return_hooker; */
safe_store_stack(return_hooker, parent, faulted);
/* *parent_ra_addr = return_hooker; */
safe_store_stack(return_hooker, parent_ra_addr, faulted);
if (unlikely(faulted))
goto out;

if (ftrace_push_return_trace(old, self_addr, &trace.depth, fp) ==
-EBUSY) {
*parent = old;
if (ftrace_push_return_trace(old_parent_ra, self_ra, &trace.depth, fp)
== -EBUSY) {
*parent_ra_addr = old_parent_ra;
return;
}

trace.func = self_addr;
/*
* Get the recorded ip of the current mcount calling site in the
* __mcount_loc section, which will be used to filter the function
* entries configured through the tracing/set_graph_function interface.
*/

insns = in_kernel_space(self_ra) ? 2 : MCOUNT_OFFSET_INSNS + 1;
trace.func = self_ra - (MCOUNT_INSN_SIZE * insns);

/* Only trace if the calling function expects to */
if (!ftrace_graph_entry(&trace)) {
current->curr_ret_stack--;
*parent = old;
*parent_ra_addr = old_parent_ra;
}
return;
out:
Expand Down
Loading

0 comments on commit 2990821

Please sign in to comment.