diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-15 17:31:43 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-15 17:31:43 -0700 |
commit | 7a1b29a82ba76427de791098c095ce31dab9333d (patch) | |
tree | 077a1563ce243b6ac619397a0b7904623a28de50 /arch/tile/kernel | |
parent | d7824370e26325c881b665350ce64fb0a4fde24a (diff) | |
parent | a5854dd7f30c3849edf9b9711362e2dd51d3f855 (diff) | |
download | op-kernel-dev-7a1b29a82ba76427de791098c095ce31dab9333d.zip op-kernel-dev-7a1b29a82ba76427de791098c095ce31dab9333d.tar.gz |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
* git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
arch/tile: don't validate CROSS_COMPILE needlessly
arch/tile: export only COMMAND_LINE_SIZE to userspace.
arch/tile: rename ARCH_KMALLOC_MINALIGN to ARCH_DMA_MINALIGN
arch/tile: Rename the hweight() implementations to __arch_hweight()
arch/tile: extend syscall ABI to set r1 on return as well.
arch/tile: Various cleanups.
arch/tile: support backtracing on TILE-Gx
arch/tile: Fix a couple of issues with the COMPAT code for TILE-Gx.
arch/tile: Use separate, better minsec values for clocksource and sched_clock.
arch/tile: correct a bug in freeing bootmem by VA for the optional second initrd.
arch: tile: mm: pgtable.c: Removed duplicated #include
arch: tile: kernel/proc.c Removed duplicated #include
Add fanotify syscalls to <asm-generic/unistd.h>.
arch/tile: support new kunmap_atomic() naming convention.
tile: remove unused ISA_DMA_THRESHOLD define
Conflicts in arch/tile/configs/tile_defconfig (pick the mainline version
with the reduced defconfig).
Diffstat (limited to 'arch/tile/kernel')
-rw-r--r-- | arch/tile/kernel/backtrace.c | 137 | ||||
-rw-r--r-- | arch/tile/kernel/compat_signal.c | 4 | ||||
-rw-r--r-- | arch/tile/kernel/intvec_32.S | 14 | ||||
-rw-r--r-- | arch/tile/kernel/proc.c | 1 | ||||
-rw-r--r-- | arch/tile/kernel/setup.c | 4 | ||||
-rw-r--r-- | arch/tile/kernel/stack.c | 8 | ||||
-rw-r--r-- | arch/tile/kernel/time.c | 33 | ||||
-rw-r--r-- | arch/tile/kernel/traps.c | 4 |
8 files changed, 138 insertions, 67 deletions
diff --git a/arch/tile/kernel/backtrace.c b/arch/tile/kernel/backtrace.c index 77265f3..d3c41c1 100644 --- a/arch/tile/kernel/backtrace.c +++ b/arch/tile/kernel/backtrace.c @@ -19,9 +19,6 @@ #include <arch/chip.h> -#if TILE_CHIP < 10 - - #include <asm/opcode-tile.h> @@ -29,6 +26,27 @@ #define TREG_LR 55 +#if TILE_CHIP >= 10 +#define tile_bundle_bits tilegx_bundle_bits +#define TILE_MAX_INSTRUCTIONS_PER_BUNDLE TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE +#define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES +#define tile_decoded_instruction tilegx_decoded_instruction +#define tile_mnemonic tilegx_mnemonic +#define parse_insn_tile parse_insn_tilegx +#define TILE_OPC_IRET TILEGX_OPC_IRET +#define TILE_OPC_ADDI TILEGX_OPC_ADDI +#define TILE_OPC_ADDLI TILEGX_OPC_ADDLI +#define TILE_OPC_INFO TILEGX_OPC_INFO +#define TILE_OPC_INFOL TILEGX_OPC_INFOL +#define TILE_OPC_JRP TILEGX_OPC_JRP +#define TILE_OPC_MOVE TILEGX_OPC_MOVE +#define OPCODE_STORE TILEGX_OPC_ST +typedef long long bt_int_reg_t; +#else +#define OPCODE_STORE TILE_OPC_SW +typedef int bt_int_reg_t; +#endif + /** A decoded bundle used for backtracer analysis. */ struct BacktraceBundle { tile_bundle_bits bits; @@ -41,7 +59,7 @@ struct BacktraceBundle { /* This implementation only makes sense for native tools. */ /** Default function to read memory. */ static bool bt_read_memory(void *result, VirtualAddress addr, - size_t size, void *extra) + unsigned int size, void *extra) { /* FIXME: this should do some horrible signal stuff to catch * SEGV cleanly and fail. @@ -106,6 +124,12 @@ static bool bt_has_addi_sp(const struct BacktraceBundle *bundle, int *adjust) find_matching_insn(bundle, TILE_OPC_ADDI, vals, 2); if (insn == NULL) insn = find_matching_insn(bundle, TILE_OPC_ADDLI, vals, 2); +#if TILE_CHIP >= 10 + if (insn == NULL) + insn = find_matching_insn(bundle, TILEGX_OPC_ADDXLI, vals, 2); + if (insn == NULL) + insn = find_matching_insn(bundle, TILEGX_OPC_ADDXI, vals, 2); +#endif if (insn == NULL) return false; @@ -190,13 +214,52 @@ static inline bool bt_has_move_r52_sp(const struct BacktraceBundle *bundle) return find_matching_insn(bundle, TILE_OPC_MOVE, vals, 2) != NULL; } -/** Does this bundle contain the instruction 'sw sp, lr'? */ +/** Does this bundle contain a store of lr to sp? */ static inline bool bt_has_sw_sp_lr(const struct BacktraceBundle *bundle) { static const int vals[2] = { TREG_SP, TREG_LR }; - return find_matching_insn(bundle, TILE_OPC_SW, vals, 2) != NULL; + return find_matching_insn(bundle, OPCODE_STORE, vals, 2) != NULL; +} + +#if TILE_CHIP >= 10 +/** Track moveli values placed into registers. */ +static inline void bt_update_moveli(const struct BacktraceBundle *bundle, + int moveli_args[]) +{ + int i; + for (i = 0; i < bundle->num_insns; i++) { + const struct tile_decoded_instruction *insn = + &bundle->insns[i]; + + if (insn->opcode->mnemonic == TILEGX_OPC_MOVELI) { + int reg = insn->operand_values[0]; + moveli_args[reg] = insn->operand_values[1]; + } + } } +/** Does this bundle contain an 'add sp, sp, reg' instruction + * from a register that we saw a moveli into, and if so, what + * is the value in the register? + */ +static bool bt_has_add_sp(const struct BacktraceBundle *bundle, int *adjust, + int moveli_args[]) +{ + static const int vals[2] = { TREG_SP, TREG_SP }; + + const struct tile_decoded_instruction *insn = + find_matching_insn(bundle, TILEGX_OPC_ADDX, vals, 2); + if (insn) { + int reg = insn->operand_values[2]; + if (moveli_args[reg]) { + *adjust = moveli_args[reg]; + return true; + } + } + return false; +} +#endif + /** Locates the caller's PC and SP for a program starting at the * given address. */ @@ -227,6 +290,11 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, int next_bundle = 0; VirtualAddress pc; +#if TILE_CHIP >= 10 + /* Naively try to track moveli values to support addx for -m32. */ + int moveli_args[TILEGX_NUM_REGISTERS] = { 0 }; +#endif + /* Default to assuming that the caller's sp is the current sp. * This is necessary to handle the case where we start backtracing * right at the end of the epilog. @@ -380,7 +448,11 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, if (!sp_determined) { int adjust; - if (bt_has_addi_sp(&bundle, &adjust)) { + if (bt_has_addi_sp(&bundle, &adjust) +#if TILE_CHIP >= 10 + || bt_has_add_sp(&bundle, &adjust, moveli_args) +#endif + ) { location->sp_location = SP_LOC_OFFSET; if (adjust <= 0) { @@ -427,6 +499,11 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, sp_determined = true; } } + +#if TILE_CHIP >= 10 + /* Track moveli arguments for -m32 mode. */ + bt_update_moveli(&bundle, moveli_args); +#endif } if (bt_has_iret(&bundle)) { @@ -502,11 +579,10 @@ void backtrace_init(BacktraceIterator *state, break; } - /* The frame pointer should theoretically be aligned mod 8. If - * it's not even aligned mod 4 then something terrible happened - * and we should mark it as invalid. + /* If the frame pointer is not aligned to the basic word size + * something terrible happened and we should mark it as invalid. */ - if (fp % 4 != 0) + if (fp % sizeof(bt_int_reg_t) != 0) fp = -1; /* -1 means "don't know initial_frame_caller_pc". */ @@ -547,9 +623,16 @@ void backtrace_init(BacktraceIterator *state, state->read_memory_func_extra = read_memory_func_extra; } +/* Handle the case where the register holds more bits than the VA. */ +static bool valid_addr_reg(bt_int_reg_t reg) +{ + return ((VirtualAddress)reg == reg); +} + bool backtrace_next(BacktraceIterator *state) { - VirtualAddress next_fp, next_pc, next_frame[2]; + VirtualAddress next_fp, next_pc; + bt_int_reg_t next_frame[2]; if (state->fp == -1) { /* No parent frame. */ @@ -563,11 +646,9 @@ bool backtrace_next(BacktraceIterator *state) } next_fp = next_frame[1]; - if (next_fp % 4 != 0) { - /* Caller's frame pointer is suspect, so give up. - * Technically it should be aligned mod 8, but we will - * be forgiving here. - */ + if (!valid_addr_reg(next_frame[1]) || + next_fp % sizeof(bt_int_reg_t) != 0) { + /* Caller's frame pointer is suspect, so give up. */ return false; } @@ -585,7 +666,7 @@ bool backtrace_next(BacktraceIterator *state) } else { /* Get the caller PC from the frame linkage area. */ next_pc = next_frame[0]; - if (next_pc == 0 || + if (!valid_addr_reg(next_frame[0]) || next_pc == 0 || next_pc % TILE_BUNDLE_ALIGNMENT_IN_BYTES != 0) { /* The PC is suspect, so give up. */ return false; @@ -599,23 +680,3 @@ bool backtrace_next(BacktraceIterator *state) return true; } - -#else /* TILE_CHIP < 10 */ - -void backtrace_init(BacktraceIterator *state, - BacktraceMemoryReader read_memory_func, - void *read_memory_func_extra, - VirtualAddress pc, VirtualAddress lr, - VirtualAddress sp, VirtualAddress r52) -{ - state->pc = pc; - state->sp = sp; - state->fp = -1; - state->initial_frame_caller_pc = -1; - state->read_memory_func = read_memory_func; - state->read_memory_func_extra = read_memory_func_extra; -} - -bool backtrace_next(BacktraceIterator *state) { return false; } - -#endif /* TILE_CHIP < 10 */ diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c index d5efb21..9c710db 100644 --- a/arch/tile/kernel/compat_signal.c +++ b/arch/tile/kernel/compat_signal.c @@ -56,13 +56,15 @@ struct compat_ucontext { sigset_t uc_sigmask; /* mask last for extensibility */ }; +#define COMPAT_SI_PAD_SIZE ((SI_MAX_SIZE - 3 * sizeof(int)) / sizeof(int)) + struct compat_siginfo { int si_signo; int si_errno; int si_code; union { - int _pad[SI_PAD_SIZE]; + int _pad[COMPAT_SI_PAD_SIZE]; /* kill() */ struct { diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index 3404c75..84f296c 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S @@ -952,7 +952,7 @@ STD_ENTRY(interrupt_return) * able to safely read all the remaining words on those cache * lines without waiting for the memory subsystem. */ - pop_reg_zero r0, r1, sp, PTREGS_OFFSET_REG(30) - PTREGS_OFFSET_REG(0) + pop_reg_zero r0, r28, sp, PTREGS_OFFSET_REG(30) - PTREGS_OFFSET_REG(0) pop_reg_zero r30, r2, sp, PTREGS_OFFSET_PC - PTREGS_OFFSET_REG(30) pop_reg_zero r21, r3, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC pop_reg_zero lr, r4, sp, PTREGS_OFFSET_REG(52) - PTREGS_OFFSET_EX1 @@ -1017,7 +1017,17 @@ STD_ENTRY(interrupt_return) { move r22, zero; move r23, zero } { move r24, zero; move r25, zero } { move r26, zero; move r27, zero } - { move r28, zero; move r29, zero } + + /* Set r1 to errno if we are returning an error, otherwise zero. */ + { + moveli r29, 1024 + sub r1, zero, r0 + } + slt_u r29, r1, r29 + { + mnz r1, r29, r1 + move r29, zero + } iret /* diff --git a/arch/tile/kernel/proc.c b/arch/tile/kernel/proc.c index 92ef925..2e02c41 100644 --- a/arch/tile/kernel/proc.c +++ b/arch/tile/kernel/proc.c @@ -23,7 +23,6 @@ #include <linux/sysctl.h> #include <linux/hardirq.h> #include <linux/mman.h> -#include <linux/smp.h> #include <asm/pgtable.h> #include <asm/processor.h> #include <asm/sections.h> diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c index 4dd21c1..e7d54c7 100644 --- a/arch/tile/kernel/setup.c +++ b/arch/tile/kernel/setup.c @@ -953,7 +953,7 @@ static void __init load_hv_initrd(void) if (rc != stat.size) { pr_err("Error reading %d bytes from hvfs file '%s': %d\n", stat.size, initramfs_file, rc); - free_bootmem((unsigned long) initrd, stat.size); + free_initrd_mem((unsigned long) initrd, stat.size); return; } initrd_start = (unsigned long) initrd; @@ -962,7 +962,7 @@ static void __init load_hv_initrd(void) void __init free_initrd_mem(unsigned long begin, unsigned long end) { - free_bootmem(begin, end - begin); + free_bootmem(__pa(begin), end - begin); } static void __init validate_hv(void) diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c index b6268d3..38a68b0b4 100644 --- a/arch/tile/kernel/stack.c +++ b/arch/tile/kernel/stack.c @@ -108,7 +108,6 @@ static bool read_memory_func(void *result, VirtualAddress address, /* Return a pt_regs pointer for a valid fault handler frame */ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt) { -#ifndef __tilegx__ const char *fault = NULL; /* happy compiler */ char fault_buf[64]; VirtualAddress sp = kbt->it.sp; @@ -146,7 +145,6 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt) } if (!kbt->profile || (INT_MASK(p->faultnum) & QUEUED_INTERRUPTS) == 0) return p; -#endif return NULL; } @@ -351,12 +349,6 @@ void tile_show_stack(struct KBacktraceIterator *kbt, int headers) kbt->task->pid, kbt->task->tgid, kbt->task->comm, smp_processor_id(), get_cycles()); } -#ifdef __tilegx__ - if (kbt->is_current) { - __insn_mtspr(SPR_SIM_CONTROL, - SIM_DUMP_SPR_ARG(SIM_DUMP_BACKTRACE)); - } -#endif kbt->verbose = 1; i = 0; for (; !KBacktraceIterator_end(kbt); KBacktraceIterator_next(kbt)) { diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c index b9ab25a..6bed820 100644 --- a/arch/tile/kernel/time.c +++ b/arch/tile/kernel/time.c @@ -36,16 +36,6 @@ /* How many cycles per second we are running at. */ static cycles_t cycles_per_sec __write_once; -/* - * We set up shift and multiply values with a minsec of five seconds, - * since our timer counter counts down 31 bits at a frequency of - * no less than 500 MHz. See @minsec for clocks_calc_mult_shift(). - * We could use a different value for the 64-bit free-running - * cycle counter, but we use the same one for consistency, and since - * we will be reasonably precise with this value anyway. - */ -#define TILE_MINSEC 5 - cycles_t get_clock_rate(void) { return cycles_per_sec; @@ -68,6 +58,14 @@ cycles_t get_cycles(void) } #endif +/* + * We use a relatively small shift value so that sched_clock() + * won't wrap around very often. + */ +#define SCHED_CLOCK_SHIFT 10 + +static unsigned long sched_clock_mult __write_once; + static cycles_t clocksource_get_cycles(struct clocksource *cs) { return get_cycles(); @@ -78,6 +76,7 @@ static struct clocksource cycle_counter_cs = { .rating = 300, .read = clocksource_get_cycles, .mask = CLOCKSOURCE_MASK(64), + .shift = 22, /* typical value, e.g. x86 tsc uses this */ .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; @@ -88,8 +87,10 @@ static struct clocksource cycle_counter_cs = { void __init setup_clock(void) { cycles_per_sec = hv_sysconf(HV_SYSCONF_CPU_SPEED); - clocksource_calc_mult_shift(&cycle_counter_cs, cycles_per_sec, - TILE_MINSEC); + sched_clock_mult = + clocksource_hz2mult(cycles_per_sec, SCHED_CLOCK_SHIFT); + cycle_counter_cs.mult = + clocksource_hz2mult(cycles_per_sec, cycle_counter_cs.shift); } void __init calibrate_delay(void) @@ -117,9 +118,14 @@ void __init time_init(void) * counter, plus bit 31, which signifies that the counter has wrapped * from zero to (2**31) - 1. The INT_TILE_TIMER interrupt will be * raised as long as bit 31 is set. + * + * The TILE_MINSEC value represents the largest range of real-time + * we can possibly cover with the timer, based on MAX_TICK combined + * with the slowest reasonable clock rate we might run at. */ #define MAX_TICK 0x7fffffff /* we have 31 bits of countdown timer */ +#define TILE_MINSEC 5 /* timer covers no more than 5 seconds */ static int tile_timer_set_next_event(unsigned long ticks, struct clock_event_device *evt) @@ -211,8 +217,7 @@ void do_timer_interrupt(struct pt_regs *regs, int fault_num) unsigned long long sched_clock(void) { return clocksource_cyc2ns(get_cycles(), - cycle_counter_cs.mult, - cycle_counter_cs.shift); + sched_clock_mult, SCHED_CLOCK_SHIFT); } int setup_profiling_timer(unsigned int multiplier) diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c index 3870abbe..0f362dc 100644 --- a/arch/tile/kernel/traps.c +++ b/arch/tile/kernel/traps.c @@ -128,7 +128,9 @@ static int special_ill(bundle_bits bundle, int *sigp, int *codep) #ifdef __tilegx__ if ((bundle & TILEGX_BUNDLE_MODE_MASK) != 0) return 0; - if (get_Opcode_X1(bundle) != UNARY_OPCODE_X1) + if (get_Opcode_X1(bundle) != RRR_0_OPCODE_X1) + return 0; + if (get_RRROpcodeExtension_X1(bundle) != UNARY_RRR_0_OPCODE_X1) return 0; if (get_UnaryOpcodeExtension_X1(bundle) != ILL_UNARY_OPCODE_X1) return 0; |