Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
Browse files Browse the repository at this point in the history
Pull sparc fixes from David Miller:
 "Several build/bug fixes for sparc, including:

  1) Configuring a mix of static vs.  modular sparc64 crypto modules
     didn't work, remove an ill-conceived attempt to only have to build
     the device match table for these drivers once to fix the problem.

     Reported by Meelis Roos.

  2) Make the montgomery multiple/square and mpmul instructions actually
     usable in 32-bit tasks.  Essentially this involves providing 32-bit
     userspace with a way to use a 64-bit stack when it needs to.

  3) Our sparc64 atomic backoffs don't yield cpu strands properly on
     Niagara chips.  Use pause instruction when available to achieve
     this, otherwise use a benign instruction we know blocks the strand
     for some time.

  4) Wire up kcmp

  5) Fix the build of various drivers by removing the unnecessary
     blocking of OF_GPIO when SPARC.

  6) Fix unintended regression wherein of_address_to_resource stopped
     being provided.  Fix from Andreas Larsson.

  7) Fix NULL dereference in leon_handle_ext_irq(), also from Andreas
     Larsson."

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc:
  sparc64: Fix build with mix of modular vs. non-modular crypto drivers.
  sparc: Support atomic64_dec_if_positive properly.
  of/address: sparc: Declare of_address_to_resource() as an extern function for sparc again
  sparc32, leon: Check for existent irq_map entry in leon_handle_ext_irq
  sparc: Add sparc support for platform_get_irq()
  sparc: Allow OF_GPIO on sparc.
  qlogicpti: Fix build warning.
  sparc: Wire up sys_kcmp.
  sparc64: Improvde documentation and readability of atomic backoff code.
  sparc64: Use pause instruction when available.
  sparc64: Fix cpu strand yielding.
  sparc64: Make montmul/montsqr/mpmul usable in 32-bit threads.
  • Loading branch information
Linus Torvalds committed Nov 10, 2012
2 parents affd9a8 + 226f7ce commit 2b1768f
Show file tree
Hide file tree
Showing 38 changed files with 291 additions and 97 deletions.
1 change: 1 addition & 0 deletions arch/sparc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ config SPARC
select HAVE_ARCH_TRACEHOOK
select SYSCTL_EXCEPTION_TRACE
select ARCH_WANT_OPTIONAL_GPIOLIB
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
select RTC_CLASS
select RTC_DRV_M48T59
select HAVE_IRQ_WORK
Expand Down
16 changes: 8 additions & 8 deletions arch/sparc/crypto/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ obj-$(CONFIG_CRYPTO_DES_SPARC64) += camellia-sparc64.o

obj-$(CONFIG_CRYPTO_CRC32C_SPARC64) += crc32c-sparc64.o

sha1-sparc64-y := sha1_asm.o sha1_glue.o crop_devid.o
sha256-sparc64-y := sha256_asm.o sha256_glue.o crop_devid.o
sha512-sparc64-y := sha512_asm.o sha512_glue.o crop_devid.o
md5-sparc64-y := md5_asm.o md5_glue.o crop_devid.o
sha1-sparc64-y := sha1_asm.o sha1_glue.o
sha256-sparc64-y := sha256_asm.o sha256_glue.o
sha512-sparc64-y := sha512_asm.o sha512_glue.o
md5-sparc64-y := md5_asm.o md5_glue.o

aes-sparc64-y := aes_asm.o aes_glue.o crop_devid.o
des-sparc64-y := des_asm.o des_glue.o crop_devid.o
camellia-sparc64-y := camellia_asm.o camellia_glue.o crop_devid.o
aes-sparc64-y := aes_asm.o aes_glue.o
des-sparc64-y := des_asm.o des_glue.o
camellia-sparc64-y := camellia_asm.o camellia_glue.o

crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o crop_devid.o
crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o
2 changes: 2 additions & 0 deletions arch/sparc/crypto/aes_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -475,3 +475,5 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("AES Secure Hash Algorithm, sparc64 aes opcode accelerated");

MODULE_ALIAS("aes");

#include "crop_devid.c"
2 changes: 2 additions & 0 deletions arch/sparc/crypto/camellia_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,5 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated");

MODULE_ALIAS("aes");

#include "crop_devid.c"
2 changes: 2 additions & 0 deletions arch/sparc/crypto/crc32c_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,5 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("CRC32c (Castagnoli), sparc64 crc32c opcode accelerated");

MODULE_ALIAS("crc32c");

#include "crop_devid.c"
2 changes: 2 additions & 0 deletions arch/sparc/crypto/des_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -527,3 +527,5 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated");

MODULE_ALIAS("des");

#include "crop_devid.c"
2 changes: 2 additions & 0 deletions arch/sparc/crypto/md5_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,5 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, sparc64 md5 opcode accelerated");

MODULE_ALIAS("md5");

#include "crop_devid.c"
2 changes: 2 additions & 0 deletions arch/sparc/crypto/sha1_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,5 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, sparc64 sha1 opcode accelerated");

MODULE_ALIAS("sha1");

#include "crop_devid.c"
2 changes: 2 additions & 0 deletions arch/sparc/crypto/sha256_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,5 @@ MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm, sparc64 sha256 op

MODULE_ALIAS("sha224");
MODULE_ALIAS("sha256");

#include "crop_devid.c"
2 changes: 2 additions & 0 deletions arch/sparc/crypto/sha512_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,5 @@ MODULE_DESCRIPTION("SHA-384 and SHA-512 Secure Hash Algorithm, sparc64 sha512 op

MODULE_ALIAS("sha384");
MODULE_ALIAS("sha512");

#include "crop_devid.c"
4 changes: 3 additions & 1 deletion arch/sparc/include/asm/atomic_64.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* atomic.h: Thankfully the V9 is at least reasonable for this
* stuff.
*
* Copyright (C) 1996, 1997, 2000 David S. Miller (davem@redhat.com)
* Copyright (C) 1996, 1997, 2000, 2012 David S. Miller (davem@redhat.com)
*/

#ifndef __ARCH_SPARC64_ATOMIC__
Expand Down Expand Up @@ -106,6 +106,8 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u)

#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)

extern long atomic64_dec_if_positive(atomic64_t *v);

/* Atomic operations are already serializing */
#define smp_mb__before_atomic_dec() barrier()
#define smp_mb__after_atomic_dec() barrier()
Expand Down
69 changes: 59 additions & 10 deletions arch/sparc/include/asm/backoff.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,46 @@
#ifndef _SPARC64_BACKOFF_H
#define _SPARC64_BACKOFF_H

/* The macros in this file implement an exponential backoff facility
* for atomic operations.
*
* When multiple threads compete on an atomic operation, it is
* possible for one thread to be continually denied a successful
* completion of the compare-and-swap instruction. Heavily
* threaded cpu implementations like Niagara can compound this
* problem even further.
*
* When an atomic operation fails and needs to be retried, we spin a
* certain number of times. At each subsequent failure of the same
* operation we double the spin count, realizing an exponential
* backoff.
*
* When we spin, we try to use an operation that will cause the
* current cpu strand to block, and therefore make the core fully
* available to any other other runnable strands. There are two
* options, based upon cpu capabilities.
*
* On all cpus prior to SPARC-T4 we do three dummy reads of the
* condition code register. Each read blocks the strand for something
* between 40 and 50 cpu cycles.
*
* For SPARC-T4 and later we have a special "pause" instruction
* available. This is implemented using writes to register %asr27.
* The cpu will block the number of cycles written into the register,
* unless a disrupting trap happens first. SPARC-T4 specifically
* implements pause with a granularity of 8 cycles. Each strand has
* an internal pause counter which decrements every 8 cycles. So the
* chip shifts the %asr27 value down by 3 bits, and writes the result
* into the pause counter. If a value smaller than 8 is written, the
* chip blocks for 1 cycle.
*
* To achieve the same amount of backoff as the three %ccr reads give
* on earlier chips, we shift the backoff value up by 7 bits. (Three
* %ccr reads block for about 128 cycles, 1 << 7 == 128) We write the
* whole amount we want to block into the pause register, rather than
* loop writing 128 each time.
*/

#define BACKOFF_LIMIT (4 * 1024)

#ifdef CONFIG_SMP
Expand All @@ -11,16 +51,25 @@
#define BACKOFF_LABEL(spin_label, continue_label) \
spin_label

#define BACKOFF_SPIN(reg, tmp, label) \
mov reg, tmp; \
88: brnz,pt tmp, 88b; \
sub tmp, 1, tmp; \
set BACKOFF_LIMIT, tmp; \
cmp reg, tmp; \
bg,pn %xcc, label; \
nop; \
ba,pt %xcc, label; \
sllx reg, 1, reg;
#define BACKOFF_SPIN(reg, tmp, label) \
mov reg, tmp; \
88: rd %ccr, %g0; \
rd %ccr, %g0; \
rd %ccr, %g0; \
.section .pause_3insn_patch,"ax";\
.word 88b; \
sllx tmp, 7, tmp; \
wr tmp, 0, %asr27; \
clr tmp; \
.previous; \
brnz,pt tmp, 88b; \
sub tmp, 1, tmp; \
set BACKOFF_LIMIT, tmp; \
cmp reg, tmp; \
bg,pn %xcc, label; \
nop; \
ba,pt %xcc, label; \
sllx reg, 1, reg;

#else

Expand Down
5 changes: 3 additions & 2 deletions arch/sparc/include/asm/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,10 @@ static inline void __user *arch_compat_alloc_user_space(long len)
struct pt_regs *regs = current_thread_info()->kregs;
unsigned long usp = regs->u_regs[UREG_I6];

if (!(test_thread_flag(TIF_32BIT)))
if (test_thread_64bit_stack(usp))
usp += STACK_BIAS;
else

if (test_thread_flag(TIF_32BIT))
usp &= 0xffffffffUL;

usp -= len;
Expand Down
17 changes: 16 additions & 1 deletion arch/sparc/include/asm/processor_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,22 @@ extern unsigned long get_wchan(struct task_struct *task);
#define KSTK_EIP(tsk) (task_pt_regs(tsk)->tpc)
#define KSTK_ESP(tsk) (task_pt_regs(tsk)->u_regs[UREG_FP])

#define cpu_relax() barrier()
/* Please see the commentary in asm/backoff.h for a description of
* what these instructions are doing and how they have been choosen.
* To make a long story short, we are trying to yield the current cpu
* strand during busy loops.
*/
#define cpu_relax() asm volatile("\n99:\n\t" \
"rd %%ccr, %%g0\n\t" \
"rd %%ccr, %%g0\n\t" \
"rd %%ccr, %%g0\n\t" \
".section .pause_3insn_patch,\"ax\"\n\t"\
".word 99b\n\t" \
"wr %%g0, 128, %%asr27\n\t" \
"nop\n\t" \
"nop\n\t" \
".previous" \
::: "memory")

/* Prefetch support. This is tuned for UltraSPARC-III and later.
* UltraSPARC-I will treat these as nops, and UltraSPARC-II has
Expand Down
5 changes: 5 additions & 0 deletions arch/sparc/include/asm/prom.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,10 @@ extern char *of_console_options;
extern void irq_trans_init(struct device_node *dp);
extern char *build_path_component(struct device_node *dp);

/* SPARC has a local implementation */
extern int of_address_to_resource(struct device_node *dev, int index,
struct resource *r);
#define of_address_to_resource of_address_to_resource

#endif /* __KERNEL__ */
#endif /* _SPARC_PROM_H */
5 changes: 5 additions & 0 deletions arch/sparc/include/asm/thread_info_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,11 @@ static inline bool test_and_clear_restore_sigmask(void)

#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)

#define thread32_stack_is_64bit(__SP) (((__SP) & 0x1) != 0)
#define test_thread_64bit_stack(__SP) \
((test_thread_flag(TIF_32BIT) && !thread32_stack_is_64bit(__SP)) ? \
false : true)

#endif /* !__ASSEMBLY__ */

#endif /* __KERNEL__ */
Expand Down
24 changes: 16 additions & 8 deletions arch/sparc/include/asm/ttable.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,9 @@ etrap_spill_fixup_64bit: \

/* Normal 32bit spill */
#define SPILL_2_GENERIC(ASI) \
srl %sp, 0, %sp; \
and %sp, 1, %g3; \
brnz,pn %g3, (. - (128 + 4)); \
srl %sp, 0, %sp; \
stwa %l0, [%sp + %g0] ASI; \
mov 0x04, %g3; \
stwa %l1, [%sp + %g3] ASI; \
Expand All @@ -398,14 +400,16 @@ etrap_spill_fixup_64bit: \
stwa %i6, [%g1 + %g0] ASI; \
stwa %i7, [%g1 + %g3] ASI; \
saved; \
retry; nop; nop; \
retry; \
b,a,pt %xcc, spill_fixup_dax; \
b,a,pt %xcc, spill_fixup_mna; \
b,a,pt %xcc, spill_fixup;

#define SPILL_2_GENERIC_ETRAP \
etrap_user_spill_32bit: \
srl %sp, 0, %sp; \
and %sp, 1, %g3; \
brnz,pn %g3, etrap_user_spill_64bit; \
srl %sp, 0, %sp; \
stwa %l0, [%sp + 0x00] %asi; \
stwa %l1, [%sp + 0x04] %asi; \
stwa %l2, [%sp + 0x08] %asi; \
Expand All @@ -427,7 +431,7 @@ etrap_user_spill_32bit: \
ba,pt %xcc, etrap_save; \
wrpr %g1, %cwp; \
nop; nop; nop; nop; \
nop; nop; nop; nop; \
nop; nop; \
ba,a,pt %xcc, etrap_spill_fixup_32bit; \
ba,a,pt %xcc, etrap_spill_fixup_32bit; \
ba,a,pt %xcc, etrap_spill_fixup_32bit;
Expand Down Expand Up @@ -592,7 +596,9 @@ user_rtt_fill_64bit: \

/* Normal 32bit fill */
#define FILL_2_GENERIC(ASI) \
srl %sp, 0, %sp; \
and %sp, 1, %g3; \
brnz,pn %g3, (. - (128 + 4)); \
srl %sp, 0, %sp; \
lduwa [%sp + %g0] ASI, %l0; \
mov 0x04, %g2; \
mov 0x08, %g3; \
Expand All @@ -616,14 +622,16 @@ user_rtt_fill_64bit: \
lduwa [%g1 + %g3] ASI, %i6; \
lduwa [%g1 + %g5] ASI, %i7; \
restored; \
retry; nop; nop; nop; nop; \
retry; nop; nop; \
b,a,pt %xcc, fill_fixup_dax; \
b,a,pt %xcc, fill_fixup_mna; \
b,a,pt %xcc, fill_fixup;

#define FILL_2_GENERIC_RTRAP \
user_rtt_fill_32bit: \
srl %sp, 0, %sp; \
and %sp, 1, %g3; \
brnz,pn %g3, user_rtt_fill_64bit; \
srl %sp, 0, %sp; \
lduwa [%sp + 0x00] %asi, %l0; \
lduwa [%sp + 0x04] %asi, %l1; \
lduwa [%sp + 0x08] %asi, %l2; \
Expand All @@ -643,7 +651,7 @@ user_rtt_fill_32bit: \
ba,pt %xcc, user_rtt_pre_restore; \
restored; \
nop; nop; nop; nop; nop; \
nop; nop; nop; nop; nop; \
nop; nop; nop; \
ba,a,pt %xcc, user_rtt_fill_fixup; \
ba,a,pt %xcc, user_rtt_fill_fixup; \
ba,a,pt %xcc, user_rtt_fill_fixup;
Expand Down
7 changes: 6 additions & 1 deletion arch/sparc/include/uapi/asm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -405,8 +405,13 @@
#define __NR_setns 337
#define __NR_process_vm_readv 338
#define __NR_process_vm_writev 339
#define __NR_kern_features 340
#define __NR_kcmp 341

#define NR_syscalls 340
#define NR_syscalls 342

/* Bitmask values returned from kern_features system call. */
#define KERN_FEATURE_MIXED_MODE_STACK 0x00000001

#ifdef __32bit_syscall_numbers__
/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
Expand Down
7 changes: 7 additions & 0 deletions arch/sparc/kernel/entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ struct popc_6insn_patch_entry {
extern struct popc_6insn_patch_entry __popc_6insn_patch,
__popc_6insn_patch_end;

struct pause_patch_entry {
unsigned int addr;
unsigned int insns[3];
};
extern struct pause_patch_entry __pause_3insn_patch,
__pause_3insn_patch_end;

extern void __init per_cpu_patch(void);
extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
struct sun4v_1insn_patch_entry *);
Expand Down
6 changes: 4 additions & 2 deletions arch/sparc/kernel/leon_kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,13 @@ static inline unsigned int leon_eirq_get(int cpu)
static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc)
{
unsigned int eirq;
struct irq_bucket *p;
int cpu = sparc_leon3_cpuid();

eirq = leon_eirq_get(cpu);
if ((eirq & 0x10) && irq_map[eirq]->irq) /* bit4 tells if IRQ happened */
generic_handle_irq(irq_map[eirq]->irq);
p = irq_map[eirq];
if ((eirq & 0x10) && p && p->irq) /* bit4 tells if IRQ happened */
generic_handle_irq(p->irq);
}

/* The extended IRQ controller has been found, this function registers it */
Expand Down
22 changes: 16 additions & 6 deletions arch/sparc/kernel/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -1762,15 +1762,25 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry,

ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;
do {
struct sparc_stackf32 *usf, sf;
unsigned long pc;

usf = (struct sparc_stackf32 *) ufp;
if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
break;
if (thread32_stack_is_64bit(ufp)) {
struct sparc_stackf *usf, sf;

pc = sf.callers_pc;
ufp = (unsigned long)sf.fp;
ufp += STACK_BIAS;
usf = (struct sparc_stackf *) ufp;
if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
break;
pc = sf.callers_pc & 0xffffffff;
ufp = ((unsigned long) sf.fp) & 0xffffffff;
} else {
struct sparc_stackf32 *usf, sf;
usf = (struct sparc_stackf32 *) ufp;
if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
break;
pc = sf.callers_pc;
ufp = (unsigned long)sf.fp;
}
perf_callchain_store(entry, pc);
} while (entry->nr < PERF_MAX_STACK_DEPTH);
}
Expand Down
Loading

0 comments on commit 2b1768f

Please sign in to comment.